ChainSync

ChainSync is the miniprotocol used to transmit chains of headers. It is a pull-based miniprotocol: data is transmitted only upon explicit request from the client.

The purpose of ChainSync is to enable the client to acquire and validate the headers of the server’s selected chain, and if it is better than the client’s current selection, direct BlockFetch to download the corresponding blocks.

tip

There usually is one ChainSync client per-peer connected to the node, such that the chain state of each peer is tracked independently.

The connection is abruptly terminated if the peer misbehaves. In particular, actions considered as misbehaviour are (not exclusively):

  • The peer violates the state machine of the protocol,
  • The server sends an invalid header,
  • The server announces a fork that is more than k blocks deep from the client’s current selection.

warning

TODO: Make this list exhaustive

The specification of the state machine of ChainSync is described in the Network documentation (design and spec).

ChainSync pipelining or pipelined diffusion

Not to be confused with protocol pipelining. The original design of ChainSync was extended with pipelining capabilities: a server can transmit a tentative header on top of the selected chain, and the invalidity of such header (or the associated body) will not cause the connection to terminate. If the client wants (by considering such header as the best known chain) it can request the body of the block via BlockFetch as usually done for any block.

This optimization is used to shorten the time it takes to diffuse chains on the network, as otherwise nodes would only announce blocks after they validated it, causing each hop through the network to be bottle-necked by validation times.

warning

TODO: expand pipelining explanation, possibly with diagrams

There are some important considerations to take into account regarding pipelined diffusion:

  • Nodes can pipeline only one header which must be on top of its current selection,
  • If the server then validates the pipelined block and finds out it was invalid, it is encouraged to announce it promptly to its clients.

warning

TODO: Are these hard requirements?

More information can be found here.

Access pattern of ChainSync

ChainSync involves potentially serving the whole chain, both the immutable part and the volatile part (the current node’s selection). As the current selection is bound to be rolled back, the ChainSync protocol has capabilities for announcing such rollbacks to clients and following rollbacks of servers.

  • For the immutable part of the chain: ChainSync accesses blocks in a sequential manner, a simple iterator over such chain would suffice.
  • For the volatile part of the chain: ChainSync accesses the current selection in a sequential manner but such selection is bound to change if a new chain is selected. The abstraction used to implement the access to the selection must be able to follow such rollbacks.
  • Blocks that become immutable usually are written to the disk as they are not used for following the current chain once the node is caught up, following the description in the k security parameter section. The implementation of ChainSync should be able to identify this situation, as blocks might be gone from the volatile part of the chain as the selection advances. This does not need to be made explicit for clients but it has to be taken into account on the implementation of the server.

Codecs

The headers sent through ChainSync on the Cardano network are tagged with the index of the era they belong to. The serialization of the header proper is its CBOR-in-CBOR representation.

serialise header = <era tag><cbor-in-cbor of header>