Skip to content
Snippets Groups Projects

netdir: New function to check consistency of a HasRelayIds

Merged Nick Mathewson requested to merge nickm/arti:resolve_relay into main
1 unresolved thread

This function will be used to look up a relay by a set of LinkSpecs given from an incoming HsDesc or INTRODUCE2 message. It differs from other "lookup relay by IDs" functions in that it needs to be able to return "here's a relay", "couldn't found a relay", or "learned that this relay is impossible."

Closes #855 (closed): This is the only new API needed for ChanTarget validation, I think.

Merge request reports

Loading
Loading

Activity

Filter activity
  • Approvals
  • Assignees & reviewers
  • Comments (from bots)
  • Comments (from users)
  • Commits & branches
  • Edits
  • Labels
  • Lock status
  • Mentions
  • Merge request status
  • Tracking
954 Some(relay) => relay,
955 None => continue,
956 };
957 if target
958 .identities()
959 .all(|wanted_id| match candidate.identity(wanted_id.id_type()) {
960 None => true,
961 Some(id) => id == wanted_id,
962 })
963 {
964 return Ok(Some(candidate));
965 } else {
966 return Err(RelayLookupError::Impossible);
967 }
968 }
969 Ok(None)
  • Comment on lines +952 to +969

    I find this a bit easier to reason about with the loop turned into a find_map + early return:

    Suggested change
    952 for id in target.identities() {
    953 let candidate = match self.by_id(id) {
    954 Some(relay) => relay,
    955 None => continue,
    956 };
    957 if target
    958 .identities()
    959 .all(|wanted_id| match candidate.identity(wanted_id.id_type()) {
    960 None => true,
    961 Some(id) => id == wanted_id,
    962 })
    963 {
    964 return Ok(Some(candidate));
    965 } else {
    966 return Err(RelayLookupError::Impossible);
    967 }
    968 }
    969 Ok(None)
    952 let candidate = match target.identities().find_map(|id| self.by_id(id)) {
    953 Some(relay) => relay,
    954 None => return Ok(None),
    955 };
    956
    957 if target
    958 .identities()
    959 .all(|wanted_id| match candidate.identity(wanted_id.id_type()) {
    960 None => true,
    961 Some(id) => id == wanted_id,
    962 })
    963 {
    964 Ok(Some(candidate))
    965 } else {
    966 Err(RelayLookupError::Impossible)
    967 }
  • I think that isn't the same? The issue is that we need to try every one of the provided identities: Even if the first identity does not give us any Relay entry, the second identity might give us a Relay with an identity that is incompatible with the first identity.

  • Hmm, AFAICT find_map does the same thing as the match self.by_id(id) from line 953: it calls self.by_id(id) for every identity in target.identities(), until it finds a result that is Some. Just like the original code, this returns immediately after finding the first relay matching one of the target identities (returning either Ok(Some(candidate)) or Err(RelayLookupError::Impossible).

  • Oh hey, you're right. Sorry there! Will fix.

  • Nick Mathewson changed this line in version 2 of the diff

    changed this line in version 2 of the diff

  • Actually, as I was rewriting this, I found a case that the old algorithm didn't handle.

    Suppose that there there are two relays R1 (with RsaId=RSA1 and Ed25519Id=None) and R2 (with RsaId=None and Ed25519Id=ED1).

    Now if we ask for a relay with the identity (RsaId=RSA1 Ed25519Id=ED1), we will be given one relay or the other, since it does match the target identity set. But the fact that two different relays match the target identity set means that there is, in fact, a contradiction here.

    (This situation is not possible in practice since in our current protocol, every relay must have an RSA identity. But if we were to add a third identity type, or make RSA optional, it would become possible, so I think it's best to revise to avoid this problem.)

    I've pushed a fixup commit to address this issue and adopt an approach more like what you recommended. What do you think?

  • Good catch! The new commit looks good to me. Feel free to merge when ready (and squash as you see fit).

  • Good catch!

    Thanks! I wouldn't have found if if you hadn't shown me that my old code was equivalent to a version that didn't check all the target.identities().

  • Please register or sign in to reply
  • gabi-250 approved this merge request

    approved this merge request

  • Nick Mathewson added 1 commit

    added 1 commit

    • 1ebf19ef - fixup! netdir: New function to check consistency of a HasRelayIds

    Compare with previous version

  • Nick Mathewson marked this merge request as draft from nickm/arti@1ebf19ef

    marked this merge request as draft from nickm/arti@1ebf19ef

  • Nick Mathewson added 1 commit

    added 1 commit

    • 4a779807 - netdir: New function to check consistency of a HasRelayIds

    Compare with previous version

  • Nick Mathewson marked this merge request as ready

    marked this merge request as ready

  • Nick Mathewson enabled an automatic merge when the pipeline for 4a779807 succeeds

    enabled an automatic merge when the pipeline for 4a779807 succeeds

  • merged

  • Nick Mathewson mentioned in commit dfa19998

    mentioned in commit dfa19998

  • Please register or sign in to reply
    Loading