Blocks in Cardano SL
This guide describes block design and the logic of the block handling.
A main block consists of a header and a body. The header contains meta-information about the block:
- A pointer to the header of previous block block signature.
- Proof of body.
- Consensus data to verify consensus algorithm.
- Some extra-data.
The block’s body contains payloads and some extra-data as well. Payloads include:
- Transactions payload. This payload is the main one. Transactions are stored in the Merkle tree. This payload includes list of witnesses as well. Please read about Transactions in Cardano SL for more info about transaction and witnesses.
- SSC payload. SSC (Shared Seed Computation) is used for the Follow-the-Satoshi algorithm. Within every epoch, slot-leaders for the next epoch must be elected. These slot-leaders will be able to generate new main blocks and add them to the ledger. So SSC is used as a source of randomness for the leader election process.
- Delegation payload. This payload consists of a list of heavyweight proxy signing keys. Please read about Stake Delegation in Cardano SL for more info.
- Update payload. It contains a proposal for software update and a list of votes for the particular update. Please read about Update System Model for more info.
A genesis block doesn’t contain transactions, and there is just one genesis block for each epoch. Genesis blocks have a header and a body, just like main blocks. The body of the block contains:
- An index of the epoch this block is associated with.
- The list of slot-leaders for this epoch. This list cannot be empty.
- Chain difficulty. It represents efforts necessary to generate a chain, it’s the number of main blocks in the chain.
Block Handling Logic
We work with blocks and block headers. Fundamentally, we can:
- create a block,
- verify a block,
- apply a block,
- rollback a block,
- get block headers by different criteria,
- classify block headers.
As mentioned above, there are two kinds of blocks: main blocks and
genesis blocks. A main block is created with the
function, and a genesis block is created with the
Main Block Creation
We try to create a new main block on top of the best chain if possible. A new block can be created if the following conditions are met:
- We know the genesis block for the epoch from the given slot ID,
- The last known block is not more than
slotSecurityParamblocks away from given slot ID.
Genesis Block Creation
First of all, we try to get the slot-leaders. If there’s no leaders or not enough blocks for LRC (Leaders and Richmen Computation), an error is reported. Otherwise we’re trying to actually create a new genesis block. However, sometimes we shouldn’t create one. For example, we shouldn’t do it for the 0th epoch because genesis block for 0th epoch is hardcoded.
We apply blocks using the
function. The sequence of blocks should be definitely valid: we must verify all
predicates and data checks regarding blocks.
Important: all blocks in that sequence must be of the same epoch!
If all conditions are met, we actually apply blocks:
Moreover, we can verify blocks before application (i.e. apply blocks only if
they’re valid). We use
function for it. If some error occurred during application, there are two
- All blocks applied inside this function will be rolled back.
- This function will try to apply as many blocks as possible.
You can think about a rollback as the opposite of application: when a rollback
is performed, all changes made by the application are cancelled. To do this, the
function is used.
We get the tip and the first block to rollback. If they do not match, an error is reported. If they match, we actually rollback the sequence of blocks:
Block Headers Classification
A header can be classified as:
A header is treated as continues if verification is succeed: header is a direct continuation of the main chain (i.e. its parent is our tip).
A header is treated as alternative if header’s parent is not our tip and it’s more difficult than our main chain.
A header is treated as invalid if there are any errors in the chain of headers or if there is no block corresponding to parent of oldest element in chain (should be one of checkpoints).
A header is treated as useless in different conditions (e.g. if header’s slot is less or equal than our tip’s slot, or header doesn’t continue main chain and is not more difficult).