Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

BlockFetch

Mini-protocol number: 3

BlockFetch is the mini-protocol in charge of diffusing block bodies. It is a pull-based mini-protocol: data is transmitted only upon explicit request from the client.

tip

There is usually one BlockFetch client per peer which is the one in charge of exchanging the messages, but BlockFetch is orchestrated by a central decision component in order to minimise network usage by fetching blocks on-demand from a single peer and avoid duplicated requests.

Received blocks are then given to the chain selection logic to determine their validity and, depending on the chain selection outcome, may be incorporated into the currently selected chain.

If the peer misbehaves, the connection will be abruptly terminated. Actions that are considered misbehaving are (not exclusively):

  • The peer violates the state machine of the protocol,
  • The server provided blocks that the client did not request,
  • The server sends a block that does not match the header it was supposed to match,
  • The server sends a block with a valid header but an invalid body.

warning

TODO: Make this list exhaustive

State machine

The state machine for BlockFetch is as follows:

stateDiagram
   direction LR
   [*] --> StIdle
   StIdle --> [*]: MsgClientDone
   StIdle --> StBusy: MsgRequestRange
   StBusy --> StIdle: MsgNoBlocks
   StBusy --> StStreaming: MsgStartBatch
   StStreaming --> StStreaming: MsgBlock
   StStreaming --> StIdle: MsgBatchDone

    classDef initiator color:#080
    classDef responder color:#008, text-decoration: underline
    class StIdle initiator
    class StBusy responder
    class StStreaming responder

State agencies

StateAgency
StIdleInitiator
StBusyResponder
StStreamingResponder

State transitions

From stateMessageParametersTo state
StIdleMsgClientDoneEnd
StIdleMsgRequestRangerangeStBusy
StBusyMsgNoBlocksStIdle
StBusyMsgStartBatchStStreaming
StStreamingMsgBlockbodyStStreaming
StStreamingMsgBatchDoneStIdle

Access pattern of BlockFetch

The requests for blocks involve sequential portions of the chain, whether in the immutable part or the volatile part of the chain.

The only special case being when a block has become immutable due to the current chain selection growing in length. In such case the abstraction used to iterate over the blocks has to be able to find the block which now would live in the immutable storage.

Codecs

The messages depicted in the state machine follow this CDDL specification:

;; messages.cddl
blockFetchMessage
     = msgRequestRange
     / msgClientDone
     / msgStartBatch
     / msgNoBlocks
     / msgBlock
     / msgBatchDone

msgRequestRange = [0, point, point]
msgClientDone   = [1]
msgStartBatch   = [2]
msgNoBlocks     = [3]
msgBlock        = [4, block.block]
msgBatchDone    = [5]

point = []                         ; the genesis point
      / [ base.slotNo, base.hash ]

;# import block as block
;# import base as base

The block is a tag-encoded value that contains CBOR-in-CBOR blocks for the particular era. Note that byron takes both the 0 and the 1 tags, one for a regular block, one for EBBs:

;; block.cddl
serialisedCardanoBlock = #6.24(bytes .cbor cardanoBlock)

cardanoBlock = byron.block
             / [2, shelley.block]
             / [3, allegra.block]
             / [4, mary.block]
             / [5, alonzo.block]
             / [6, babbage.block]
             / [7, conway.block]

;# import byron as byron
;# import shelley as shelley
;# import allegra as allegra
;# import mary as mary
;# import alonzo as alonzo
;# import babbage as babbage
;# import conway as conway