Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 29 additions & 3 deletions src/devnet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,23 @@ pub struct DevnetConfig {
/// When `Some`, nodes will use this network (e.g. Anvil testnet) for
/// on-chain verification. Defaults to Arbitrum One when `None`.
pub evm_network: Option<EvmNetwork>,

/// Bind nodes to loopback addresses (`127.0.0.1`/`::1`) only.
///
/// When `true` (the default), nodes listen on loopback only — the
/// historical single-host devnet behavior, suitable for development
/// and integration tests where every node and every client run on
/// the same machine.
///
/// When `false`, nodes bind to all interfaces (`0.0.0.0`/`::`), which
/// is required for cross-host LAN devnets where client machines need
/// to reach the devnet's nodes via the lab server's LAN IP. The
/// 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.
///
Copy link

Copilot AI Apr 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested 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.
///

Copilot uses AI. Check for mistakes.
/// Passed through to saorsa-core's `NodeConfigBuilder::local`.
pub loopback_only: bool,
}

impl Default for DevnetConfig {
Expand All @@ -185,6 +202,7 @@ impl Default for DevnetConfig {
enable_node_logging: false,
cleanup_data_dir: true,
evm_network: None,
loopback_only: true,
}
}
}
Expand Down Expand Up @@ -574,9 +592,17 @@ impl Devnet {
debug!("Starting node {} on port {}", node.index, node.port);
*node.state.write().await = NodeState::Starting;

let mut core_config = CoreNodeConfig::builder()
.port(node.port)
.local(true)
let builder = CoreNodeConfig::builder().port(node.port);
// Historical single-host devnet path uses local(true), which auto-enables
// allow_loopback for routing. LAN devnet path binds all interfaces and
// re-enables allow_loopback explicitly so inter-node bootstrap via
// loopback addresses continues to work.
let builder = if self.config.loopback_only {
builder.local(true)
} else {
builder.local(false).allow_loopback(true)
};
let mut core_config = builder
.max_message_size(crate::ant_protocol::MAX_WIRE_MESSAGE_SIZE)
.build()
.map_err(|e| DevnetError::Core(format!("Failed to create core config: {e}")))?;
Expand Down
Loading