Merged
Conversation
a2177b1 to
e7ca9f8
Compare
Evanev7
requested changes
Mar 11, 2026
Member
Evanev7
left a comment
There was a problem hiding this comment.
at first pass this seems fine. i expect some breaking changes here in the future as we work around some of libp2ps issues and move off gossipsub for our data plane.
src/exo/main.py
Outdated
| parser.add_argument( | ||
| "--libp2p-port", | ||
| type=int, | ||
| default=None, |
Member
There was a problem hiding this comment.
we could also default to 0 and not have the port be nullable either.
Contributor
Author
There was a problem hiding this comment.
Yep, make sense. I'll make the change
|
|
||
| #[new] | ||
| fn py_new(identity: Bound<'_, PyKeypair>) -> PyResult<Self> { | ||
| #[pyo3(signature = (identity, bootstrap_peers=vec![], listen_port=None))] |
Member
There was a problem hiding this comment.
don't provide default arguments when we won't make use of them
src/exo/routing/router.py
Outdated
Comment on lines
+108
to
+109
| bootstrap_peers: list[str] | None = None, | ||
| listen_port: int | None = None, |
Member
There was a problem hiding this comment.
ditto. bootstrap_peers doesn't need nullability at all.
e46d29f to
27d42d8
Compare
Address review feedback: use zero-values (empty sequence, port 0) instead of Option/None throughout the bootstrap peers API. Defaults live only in main.py's argument parser, not in the Rust PyO3 boundary. Signed-off-by: DeepZima <deepzima@outlook.com>
b4c4c16 to
4090a69
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Enabling peers to be discovered in environments where mDNS is unavailable (SSH sessions, headless servers, Docker).
Motivation
Exo discovers peers exclusively via mDNS, which works great on a local network but breaks once you move beyond a single L2 broadcast domain:
Related works:
#1488 (working implementation made by @AlexCheema and closed because SSH had a GUI workaround),
#1023 (Headscale WAN then closed due to merge conflicts),
#1656 (discovery cleanup, open).
This PR introduces an optional bootstrap mechanism for peer discovery while leaving the existing mDNS behavior unchanged.
Changes
Adds two new CLI flags:
--bootstrap-peers(env:EXO_BOOTSTRAP_PEERS) — comma-separated libp2p multiaddrs to dial on startup and retry periodically--libp2p-port— fixed TCP port for libp2p to listen on (default: OS-assigned). Required when bootstrap peers, so other nodes know which port to dial.8 files:
rust/networking/src/discovery.rs: Store bootstrap addrs, dial in existing retry looprust/networking/src/swarm.rs: Threadbootstrap_peersparameter toBehaviourrust/networking/examples/chatroom.rs: Updated call site for new create_swarm signaturerust/networking/tests/bootstrap_peers.rs: Integration testsrust/exo_pyo3_bindings/src/networking.rs: Accept optionalbootstrap_peersin PyO3 constructorrust/exo_pyo3_bindings/exo_pyo3_bindings.pyi: Update type stubsrc/exo/routing/router.py: Pass peers toNetworkingHandlesrc/exo/main.py:--bootstrap-peersCLI arg +EXO_BOOTSTRAP_PEERSenv varWhy It Works
Bootstrap peers are dialed in the existing retry loop — the same path taken by peers when mDNS-discovered. The swarm handles connection, Noise handshake, and gossipsub mesh joining from there.
PeerId is intentionally not required in the multiaddr, the Noise handshake discovers it.
Docker Compose example:
Test Plan
Manual Testing
Docker Compose config
Two containers on a bridge network (
172.30.20.0/24), fixed IPs,--libp2p-port 30000, cross-referencing--bootstrap-peers.Both nodes found each other and established a connection then ran the election protocol.
Automated Testing
4 Rust integration tests in
rust/networking/tests/bootstrap_peers.rs(cargo test -p networking):two_nodes_connect_via_bootstrap_peerscreate_swarm_with_empty_bootstrap_peerscreate_swarm_ignores_invalid_bootstrap_addrscreate_swarm_with_fixed_portlisten_portparameter worksAll 4 pass. The connection test takes ~6s