Skip to content

Conversation

xDimon
Copy link

@xDimon xDimon commented Oct 15, 2025

Summary

This PR introduces the x-shadow feature, which allows building Litep2p compatible with the Shadow network simulator.
When this feature is enabled, outgoing socket binding is disabled to prevent address collisions that occur under Shadow, which otherwise lead to AddrInUse errors when connecting to remote peers.

Changes

  • Added a new Cargo feature: x-shadow.
  • Disabled explicit binding of outgoing sockets when the feature is active.
  • djusted connection logic to comply with Shadow environment constraints.
  • Updated build configuration and conditional compilation accordingly.

Motivation

Under the Shadow simulator, each node runs in an isolated process namespace but shares the same IP address space.
Explicitly binding outgoing sockets may cause multiple nodes to use the same source address, resulting in EADDRINUSE collisions.
The x-shadow feature resolves this by skipping the bind step for outgoing connections, ensuring stable network behavior in simulation.

Compatibility

  • Activated via Cargo feature flag: --features x-shadow.
  • Has no effect on normal (non-Shadow) builds or runtime behavior.
  • Safe to merge — default build remains unchanged.

Testing

  1. Build with --features x-shadow.
  2. Run the binary under Shadow simulation.
  3. Verify that connections between peers establish successfully.
  4. Ensure no AddrInUse errors occur during parallel outgoing connections.
  5. Confirm clean shutdown and resource release after simulation.

Signed-off-by: Dmitriy Khaustov aka xDimon <[email protected]>
@xDimon xDimon changed the title fix: reuseaddr error under shadow Add x-shadow feature for Shadow simulation compatibility Oct 15, 2025
@dmitry-markin
Copy link
Collaborator

Hi @xDimon and thanks for contributing! The issue looks to me as networking configuration problem and not as the code limitation. If the processes under Shadow share the same address space (do you mean local IP?), the nodes must be configured to listen on different ports or other bad things will happen. Reusing the same local listen port the process is already listening on should not be the problem then.

Does this make sense?

@xDimon
Copy link
Author

xDimon commented Oct 20, 2025

@dmitry-markin
Even though the hosts in the simulation are isolated, we still assign different addresses and ports. However, this error occurs when attempting to bind a listening IP and port for an outgoing connection. As far as I know, this technique is used to allow incoming connections through NAT. However, it seems Shadow doesn't support this behavior, and when we bind a socket to an address that is already bound to the same address, we get an error. PR disables this feature in the library for builds used in the simulation.

@xDimon
Copy link
Author

xDimon commented Oct 20, 2025

It's needed for paritytech/polkadot-sdk#10055

socket.set_nonblocking(true)?;
socket.set_nodelay(nodelay)?;

#[cfg(not(feature = "x-shadow"))]
Copy link
Collaborator

Choose a reason for hiding this comment

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

There is an existing runtime configuration for this in tcp::Config (and similarly for websocket):

pub reuse_port: bool,

@dmitry-markin
Copy link
Collaborator

It's needed for paritytech/polkadot-sdk#10055

If you really need this, I would suggest doing it in polkadot-sdk by setting reuse_port: false in TCP & WS config during litep2p initialization: https://github.com/paritytech/polkadot-sdk/blob/db5c89ffb65503c766fec651cf4dabfa8c820398/substrate/client/network/src/litep2p/mod.rs#L323-L335

But this will break the mechanism of detecting the external address, so you will need to manually specify --public-addr for the node if it's different from --listen-addr.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants