P2P Networking
In decentralized networks, the peer-to-peer (P2P) layer is responsible for connecting nodes and enabling data exchange.
The Midnight Node leverages the default Polkadot SDK Rust LibP2P implementation. Key components include the following.
Discovery Mechanisms
To participate in a decentralized network, a node must discover and connect to peers. Midnight supports several peer discovery strategies:
Bootstrap Nodes
Nodes can be configured with a list of predefined peers, known as bootstrap nodes. These are hard-coded identities and addresses provided in the network configuration. On startup, the node attempts to connect to these trusted peers to join the network and begin learning about others.
mDNS (Multicast DNS)
For local network discovery, mDNS enables nodes to find peers on the same LAN using UDP broadcast. This is useful for development environments, testnets, or networks where peers are in close proximity. The use of mDNS can be enabled or disabled via network settings.
Kademlia DHT (Random Walk)
Once connected to at least one peer, the node engages in a Kademlia-based random walk on each configured chain’s Distributed Hash Table (DHT). This involves sending FIND_NODE queries to discover additional peers. Over time, the node builds a more complete view of the network, improving connectivity and resilience.
Connection Establishment
Transport Layer
When Node A (Alice) wants to connect to Node B (Bob), and knows Bob's address, it initiates a connection using one of several supported transport protocols:
- TCP/IP: Traditional IPv4 or IPv6 socket connections.
- WebSockets: Built on top of TCP, allowing browser-friendly or proxy-compatible connections via WebSocket framing.
- DNS: Domain names can be used as node addresses, resolved to IPs during the connection process.
Encryption and Multiplexing
Once the underlying transport is established, the connection is upgraded through a series of negotiated protocols:
- Encryption is handled using the Noise Protocol Framework, ensuring end-to-end confidentiality and integrity.
- Stream Multiplexing is typically achieved using Yamux, allowing multiple logical streams (substreams) to operate concurrently over a single physical connection.
These upgrades are negotiated using Multistream-Select, a protocol that lets peers choose compatible encryption and multiplexing options.
Substream Protocols
Once the connection is multiplexed, peers open multiple substreams, each dedicated to a specific application-level protocol. These include:
- Ping: For liveness checks and latency measurements.
- Request-Response: For structured data exchange (e.g., block or transaction queries).
- Notifications: For broadcasting events like new transactions, block announcements, finality updates, and light-client state syncs.
Peer Identification
Each node identifies itself using a unique ed25519 public key, separate from the keypair used for consensus message signing. This identity key is exchanged during the handshake process and used to authenticate the peer throughout the session.