From 65d11e65a43336530949baa4e18a9a40a6079446 Mon Sep 17 00:00:00 2001 From: Nic-dorman Date: Wed, 29 Apr 2026 13:57:09 +0100 Subject: [PATCH 1/2] feat(devnet): add loopback_only flag for LAN devnet support 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) --- src/devnet.rs | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/src/devnet.rs b/src/devnet.rs index e70c030..1899504 100644 --- a/src/devnet.rs +++ b/src/devnet.rs @@ -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, + + /// 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. + /// + /// Passed through to [`saorsa_core::NodeConfigBuilder::local`]. + pub loopback_only: bool, } impl Default for DevnetConfig { @@ -185,6 +202,7 @@ impl Default for DevnetConfig { enable_node_logging: false, cleanup_data_dir: true, evm_network: None, + loopback_only: true, } } } @@ -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}")))?; From b651365f869c0ab8640d8bef4ffd531c24cb5aab Mon Sep 17 00:00:00 2001 From: Nic-dorman Date: Wed, 29 Apr 2026 14:51:52 +0100 Subject: [PATCH 2/2] fix(devnet): drop broken intra-doc link in loopback_only docstring `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) --- src/devnet.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/devnet.rs b/src/devnet.rs index 1899504..faf5a01 100644 --- a/src/devnet.rs +++ b/src/devnet.rs @@ -179,7 +179,7 @@ pub struct DevnetConfig { /// mode so inter-node bootstrap (which still uses loopback addresses /// on the lab host) continues to work. /// - /// Passed through to [`saorsa_core::NodeConfigBuilder::local`]. + /// Passed through to saorsa-core's `NodeConfigBuilder::local`. pub loopback_only: bool, }