# `sc-network` overview
This documents describes the current state of `sc-network` crate, including the changes introduced in [PR #12828](https://github.com/paritytech/substrate/pull/12828). There also exist an older version of [this document](https://www.notion.so/paritytechnologies/sc-network-crate-eed45792fe434380a9af1587de26e72b) which is not up to date but contains valuable information nonetheless.
`sc-network` crate is built on top of `libp2p`. `Libp2p` provides the capability of establishing connections, opening new substreams multiplexed on the opened connection(s) and exchaning information between the nodes by sending data on these substream. Currently only TCP of the L4 protocols is supported for transmission.
Each protocol in Substrate has its own substream and most protocols live outside of `sc-network`. These protocols include `Transactions`, `GRANDPA`, `BEEFY` and the syncing protocol.

**Figure 1 demonstrates the relationships between different components in the `sc-network` crate**
## `Notifications`
Notifications protocol lives below the `Protocol`. It is responsible for opening substreams with remote peers and handling incoming substreams. The implementation is a complex state machine as it has to handle all the cases of the connection and associated substream(s) being in different states. `Notification` doesn't decide which connections are accepted and which are rejected but instead dispatches the substream information to `Peerset` which then validates the substream based on available slots and either accepts or rejects the substream.
As both peers can dial each other simultaneously, `Notifications` has the capability having two simultaenous connections open at the same time. One of the connections can be considered "closed" (inactive) and the peers are still able to communicate through the other open connection. Each substream is associated with a notification sink which allows protocols to send notifications to the remote peer over the designated protocol. If node has two connections open and the active connection is closed, the notification sink is replaced to point to the other, previously inactive connection.
All events related to substreams (open, close, notification received, notification sink replaced) are forwarded to `Protocol` which then forwards them to `Behaviour` which then forwards them to `NetworkWorker` which then sends events to all protocols that have an active `NetworkEventStream` open. There is a plan to reduce the inefficiences of this system and pass events directly from `Notifications` to protocols.
## `Peerset`
Peerset is a separate entity outside of `sc-network`. Its job is to validate inbound connections against the available slots, update peer reputation based on updates received from other protocols and attempt to establish outbound connections if there are available outbound slots and known peers.
`Notifications` interacts with `Peerset` by sending information about unvalidated inbound substream requests which the `Peerset` validates and either rejects or accepts. `Peerset` in turn interacts with `Notifications` by asking it to open substreams with peers it has chosen for outbound connections.
Each protocol has a number of inbound and outbound slots. These slots control how many inbound and outbound substreams each protocol can hold. `Transactions` and `GRANDPA` follow the peerset of the sync protocol. What this means is that when a peer is accepted by the sync protocol, they're notified of this and add this peer to their set of reserved nodes and attempt to open a substream with the peer. Reserved nodes do not occupy slots so if there are 50 slots and 10 reserved nodes, the total number of substreams the protocol can establish is 60.
Implementation for `Peerset` can be found from `client/peerset/src/lib.rs`.
## `NetworkWorker`
`NetworkWorker` is the main object of `sc-network`. It is responsible for polling both `libp2p`'s `Swarm` object as well handling all incoming events sent by different protocols through `NetworkService`. The implementation for `NetworkWorker` can be found from `client/network/src/service.rs` and it basically consists of two things:
* events coming from upper-layer protocols such as `Transactions` or `GRANDPA`
* events coming from `Notifications` and `libp2p`
The code is very simple and acts basically as a message dispatcher between the upper and lower protocol layers.
## `NetworkService`
In addition to opening substreams, the protocol also wants to communicate with the remote peer. This is done by using the `NetworkService` abstraction which allows protocols to interact with `NetworkWorker` and by extension the entire `sc-network` crate. `NetworkService` is a handle implementing all kinds of traits such as `NetworkNotification`, `NetworkRequest` and `NetworkPeers`. If, e.g., `Transactions` wishes to send a notification (a transaction) to some peer it's connected to, it calls `NetworkNotification:write_notification()` or if it wishes to disconnect a peer, it calls `NetworkPeers::disconnect()`. This doesn't disconnect the peer from the entire blockchain but only closes the substream of the protocol.
The full functionality that `NetworkService` supports can be found from `client/network/common/service.rs`. It lists all the traits `NetworkService` implements and the implementation of these traits can be found from `client/network/src/service.rs`. This file also provides the full list of `NetworkService` events.
## Syncing protocol
Syncing is the most complicated protocol (excluding `GRANDPA`). It consist of four things:
* `SyncingEngine` which is the syncing ripped out of `Protocol`
* `SyncingService` which provides the ability to follow syncing progress and interact with it
* `ChainSync` which is the syncing state machine responsible for keeping local node's chain in sync with the network
* Block/Warp/State sync requests handlers
Syncing interacts with many other components of Substrate: `GRANDPA`, `BEEFY` `NetworkGossip`, `Transactions`, import queue, `Notifications` and `libp2p`'s request-response protocol.
The main object of syncing is the `SyncingEngine`. It's responsible for driving `ChainSync` and processing incoming events from other protocols. `GRANDPA` might, e.g., need to send a justification request, or a block must be announced, it's first processsed by the `SyncingEngine` which then either processes the event itself or dispatches it to `ChainSync`. Other protocols can interact with `SyncingEngine` through the `SyncingService` abstraction which is modeled the `NetworkService` concept. Full capabilities of `SyncingService` are show in `client/network/sync/service/chain_sync.rs`.
The state machine implementation of syncing can be found from `client/network/sync/src/lib.rs` and it's called `ChainSync`. It works by accepting connections from peers and checking their best block information against the information locally available and scheduling blocks for downloading if it notices the new peer has block the local node doesn't know about. The same logic also applies to received block announcement for blocks that the local node was unaware of. `ChainSync` also directly interacts with the import queue by sending it blocks and justifications it has received from the network.
Part of syncing, though not true on the code level right now, are the request handlers. Due to a bug in the code, block/warp/state sync requests are processed even if the syncing code has rejected the peer because the connections linger on as the substream rejection is not reported correctly on the protocol level. These handlers receive request from remote peers based on information local node has advertised either in the handshake or block announcement message.
Design on the [Sync 2.0](https://github.com/paritytech/substrate/issues/10740) has started and it will be out at some point. The goal is to modularize the syncing protocol, split into clearly separate syncing modes and hopefully simplify the code to a point where it's not so scary task to modify it.