Skip to content
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

refactor: streamline discovery and node info types #3175

Open
wants to merge 19 commits into
base: main
Choose a base branch
from

Conversation

Frando
Copy link
Member

@Frando Frando commented Feb 10, 2025

Description

Adds a NodeData struct that contains the information about a node that can be published in discovery services. This struct is both used in iroh_relay::dns::NodeInfo and in iroh::discovery::Discovery. Previously, we had this information in two different structs, which means they had to be kept in sync manually.

This PR also serves these prupsoes:

  • We want to add some "user defined data" to discovery (see feat(iroh): publish and resolve user-defined data in discovery #3176). This would add a third argument to Discovery::publish; with this PR instead we can just add it as an optional field to NodeData.
  • It makes it possible to potentially add data to discovery after 1.0. The fields of NodeData are private, so we can add fields, and setter/getter methods, without this being a semver-breaking change.

Breaking Changes

  • iroh::discovery::Discovery::publish now takes data: &NodeData as its single argument. iroh::discovery::NodeData is a re-export of iroh_relay::dns::node_info::NodeData, and contains relay URL and direct addresses. See docs for NodeData for details.
  • iroh::discovery::DiscoveryItem no longer has any public fields. There are now getters for the contained data.
  • iroh_relay::dns::node_info::NodeInfo is changed.
    • NodeInfo::new now has a single NodeId argument. Use NodeInfo::with_direct_addresses and NodeInfo::with_relay_url to set addresses and relay URL. Alternatively, use NodeInfo::from_parts and pass a NodeData struct.
    • NodeInfo now has two public fields node_id: NodeId and data: NodeData, and setter and getter methods for the relay URL and direct addresses.
  • iroh::discovery::pkarr::PkarrPublisher::update_addr_info now takes a NodeData argument

Notes & open questions

Change checklist

  • Self-review.
  • Documentation updates following the style guide, if relevant.
  • Tests if relevant.
  • All breaking changes documented.

@Frando Frando changed the title refactor: DiscoveryData type for publish in discovery refactor: DiscoveryData type for publishing node info in discovery Feb 10, 2025
Copy link

github-actions bot commented Feb 10, 2025

Documentation for this PR has been generated and is available at: https://n0-computer.github.io/iroh/pr/3175/docs/iroh/

Last updated: 2025-02-13T23:21:37Z

Copy link

github-actions bot commented Feb 10, 2025

Netsim report & logs for this PR have been generated and is available at: LOGS
This report will remain available for 3 days.

Last updated for commit: f1eadfb

@Frando Frando changed the title refactor: DiscoveryData type for publishing node info in discovery refactor: streamline discovery types Feb 11, 2025
@Frando Frando changed the title refactor: streamline discovery types refactor: streamline discovery and node info types Feb 11, 2025
@ramfox
Copy link
Contributor

ramfox commented Feb 11, 2025

Okay, my previous comment about the NodeInfo API comes from a bit of confusion on my part.

I very much agree with your goal of structuring this in a way where we can make future changes without breaking the 1.0 API.

What are your thoughts on how the current code in this PR is going to affect DiscoveryItem? Will the user defined data be a separate field? If so, we would still be breaking the discovery API each time we add anything to Discovery, since it would need to be reported in the DiscoveryItem.

DiscoveryItem currently contains a NodeAddr. NodeAddr currently contains node_id, relay_url, and direct_addresses, this is everything in the NodeInfo, only missing the future user defined data field.

So what if instead:

  • NodeInfo is the opaque struct (rather than NodeData), with getters and setters and no public fields
  • Discovery::publish now takes a NodeInfo (but we would likely tell discovery implementers to ignore the node_id field. this is the "orange" flag for this proposal, in my opinion)
  • DiscoveryItem now contains a NodeInfo, rather than a NodeAddr, and we add a node_addr method in DiscoveryItem to smooth this transition.

I guess another option would be:

  • NodeData is the opaque struct, with getters and setters and no public fields
  • Discovery::publish takes a NodeData
  • DiscoveryItem has a node_id field and a data field (w/ an item.node_addr() field to smooth the transition)

The reason I prefer the first option is we have one less public struct to maintain, though we would need to add documentation to the Discovery::publish trait that you should likely not be using the node_id field in NodeInfo for anything.

I appreciate the push to make the initial RFC more robust!

Thoughts?

@Frando
Copy link
Member Author

Frando commented Feb 12, 2025

Thanks for the review!

I agree that DiscoveryItem should reuse the NodeData or NodeInfo, so that there really is only one struct that contains all the info about a node that we support in discovery.

I'm less sure about publish taking NodeInfo which contains a node id. I think it is a bit of a bad API to tell people to ignore a field. So my gut feeling is to keep NodeData. What we could do is to have NodeInfo deref to NodeData, so that all methods on NodeData are available directly on NodeInfo as well, maybe I'll try this out next to see how it feels.

@Frando
Copy link
Member Author

Frando commented Feb 12, 2025

I pushed a commit that implements the following:

  • NodeInfo has a NodeId and a NodeData. It derefs to NodeData, so methods from there are available directly on NodeInfo. It can be converted from and into a NodeAddr.
  • NodeData has relay url and direct addresses (and soon user data). All fields are private, and there's getter and setter methods for all fields.
  • DiscoveryItem now also has all fields private, and just stores a NodeInfo, the provenance and last_updated (which me might want to remove, but that's for another PR). No direct data fields anymore! It also derefs to NodeData, so you can just call item.relay_url() etc.

Also see generated docs: DiscoveryItem, NodeInfo, NodeData (actual doc comments will need another pass, but the structure is quite OK now I think?)

I'm quite happy with this, and it made #3176 even simpler.

Let me know what you think

@Frando Frando marked this pull request as ready for review February 12, 2025 13:49
@Frando
Copy link
Member Author

Frando commented Feb 13, 2025

I pushed another commit that adapts the StaticProvider to also use NodeInfowhere appropriate, so that adding more things to NodeInfo (i.e. UserData with #3176 ) just works.

@Frando Frando force-pushed the feat/discovery-data branch from 761ffe7 to 181a4be Compare February 13, 2025 23:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: 🏗 In progress
Development

Successfully merging this pull request may close these issues.

2 participants