feat(devnet): add loopback_only flag for LAN testnet support#84
feat(devnet): add loopback_only flag for LAN testnet support#84Nic-dorman wants to merge 2 commits intomainfrom
Conversation
Adds an opt-in `loopback_only: bool` field on `DevnetConfig`, defaulting to `true`. When set to `false`, devnet nodes bind to all interfaces (saorsa-core `local=false`) and explicitly enable `allow_loopback` in the routing layer so inter-node bootstrap via loopback addresses on the lab host continues to work. The historical single-host code path is preserved unchanged: existing callers using `DevnetConfig::default()`, `::minimal()`, or `::small()` get bit-identical builder calls and behavior. 448/448 lib tests pass without modification. Use case: cross-host LAN devnets for app testing. One machine hosts the devnet stack (Anvil + N antnodes); other devices on the same LAN connect as thin testers via a sibling HTTP server (separate repo) that serves the rewritten devnet manifest. Avoids rebuilding the full stack on every Windows/macOS/Linux developer laptop. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Adds an opt-in loopback_only switch to devnet orchestration so devnet nodes can be bound to all interfaces for cross-host LAN scenarios while keeping the default behavior unchanged for existing callers.
Changes:
- Added
loopback_only: booltoDevnetConfigwith a default oftrue(preserves historical loopback-only behavior). - Updated
Devnet::start_nodeto choose betweenlocal(true)andlocal(false); whenlocal(false)is used,allow_loopback(true)is set to preserve intra-host loopback bootstrap behavior.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| /// transport-layer `allow_loopback` flag is enabled explicitly in this | ||
| /// mode so inter-node bootstrap (which still uses loopback addresses | ||
| /// on the lab host) continues to work. | ||
| /// |
There was a problem hiding this comment.
The docs for loopback_only read a bit like setting it to false is sufficient for cross-host clients. In this module bootstrap_addrs() (and the ant-devnet manifest it produces) still always uses Ipv4Addr::LOCALHOST, so remote clients will need a rewritten/overridden bootstrap list even when nodes bind to 0.0.0.0/::. Consider adding an explicit note to avoid confusion about what this flag does/doesn’t change.
| /// | |
| /// | |
| /// Note: this only affects the addresses nodes bind/listen on. It does | |
| /// not rewrite bootstrap addresses produced by this module (including | |
| /// [`Self::bootstrap_addrs()`] and the generated `ant-devnet` manifest), | |
| /// which still use localhost addresses. Remote clients on other hosts | |
| /// must therefore override or rewrite the bootstrap list to use a | |
| /// reachable LAN/WAN IP for the devnet host. | |
| /// |
`saorsa_core::NodeConfigBuilder` isn't re-exported at the crate root, so the intra-doc reference fails under `RUSTDOCFLAGS=-D warnings` in the Documentation CI job. Replaced with plain prose + a code span. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Summary
Adds an opt-in
loopback_only: boolfield onDevnetConfig(defaulttrue) so the devnet harness can bind nodes to all interfaces insteadof loopback-only. Default-true preserves bit-identical behavior for all
existing callers;
loopback_only: falseenables a cross-host LANdevnet path.
This is purely a dev-orchestration change —
Devnet/DevnetConfigare dev-only and not on the production node runtime path.
Why — LAN testnets for app testing
Every developer running an Autonomi-network app today needs to spin up
their own 25-node + Anvil stack locally to test against. That doesn't
scale across mixed-OS test fleets (Windows + macOS + Linux laptops on
one team). The motivating use case here is a "lab box" that hosts the
devnet once, with other devices on the same LAN acting as thin testers
that fetch the bootstrap manifest and run
ant file upload/download.A sibling tool (separate repo,
testnet-lan) serves the rewrittenmanifest over HTTP. It's not in this PR — that lives independently and
consumes whatever this exposes.
Changes
src/devnet.rs:loopback_only: boolfield onDevnetConfig.Defaultimpl setsloopback_only: true.start_nodebifurcates the saorsa-core builder:loopback_only=true: identical to today —.local(true)only.loopback_only=false:.local(false).allow_loopback(true). Theexplicit
allow_loopbackis required because saorsa-core'slocal(false)would otherwise default it tofalse, which wouldreject the loopback bootstrap addresses devnet nodes still use to
dial each other on the same lab host.
29 insertions, 3 deletions. No changes to manifest types or other public
API.
Backwards compatibility
DevnetConfig::default()loopback_only: true— historical behaviorDevnetConfig::minimal()/small()..Self::default()— historicalDevnetConfig { evm_network: …, ..default() })..Default::default()so this is unlikely in practiceCompatibility with saorsa-labs/saorsa-core#105
This change is complementary, not in conflict, with
saorsa-labs/saorsa-core#105
(LAN-scoped DHT addresses). The two operate at different layers:
peers and tags them as
AddressType::Lan.When both land, the LAN testnet path improves: with
loopback_only=false,saorsa-transport's
listen_addrs()reports LAN addresses, andsaorsa-core#105's
peer_can_receive_lan_addressesheuristic correctlyhands LAN-tagged entries to clients on the same network. saorsa-core#105
alone wouldn't enable cross-host LAN devnets — without this PR, the
devnet has no LAN address to share. They depend on each other for
the full LAN-testnet story.
maybe_swap_same_lan_ip_to_loopbackfrom #105 only triggers when a peerannounces our own LAN IP back at us (intra-host case), which doesn't
fire for clients on different hosts. No interaction issue.
Test plan
cargo build --libcleancargo test --lib: 448/448 passing on the unchanged default pathcargo fmt --all -- --checkcleannever_looplint atline ~770 fires on bare
maintoo; not introduced here)sibling testnet-lan tool reaching public review
🤖 Generated with Claude Code