Skip to content

Commit

Permalink
Apply suggestions from code review
Browse files Browse the repository at this point in the history
Co-authored-by: José Daniel Hernández <[email protected]>
Co-authored-by: hrxi <[email protected]>
  • Loading branch information
3 people authored Nov 20, 2024
1 parent 3b6fc86 commit 75f75d7
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 23 deletions.
34 changes: 17 additions & 17 deletions learn/protocol/block-format.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,28 @@

In the Nimiq PoS blockchain, blocks are categorized into **microblocks** and **macroblocks**. Each type has a different role in maintaining the blockchain:

- **Micro Blocks**: include user-generated transactions and are produced and signed by a validator according to the validator selection process. If a validator fails to produce a micro block on time, a [skip block](/learn/protocol/validators/skip-blocks.md) is added.
- **Micro Blocks**: include user-generated transactions and are produced and signed by a validator according to the validator selection process. If a validator fails to produce a micro block on time, a [skip block](/learn/protocol/validators/skip-blocks.md) is produced instead.
- **Macro Blocks**: these do not contain user transactions, ensure finality, and are produced using the Tendermint consensus algorithm. There are two types: election and checkpoint.

## Micro Blocks

Micro blocks are the blocks for processing transactions on the Nimiq PoS blockchain. A validator, randomly selected through a [VRF based process](/learn/protocol/verifiable-random-functions.md) that ensures randomness and decentralization, produces a new micro block. If a validator fails to produce a block, the remaining validators can agree on a skip block to maintain the blockchain's continuity. The structure of a micro block is divided into three parts: **header**, **body**, and **justification**.
Micro blocks are the blocks for including transactions on the Nimiq PoS blockchain. A validator, randomly selected through a [VRF based process](/learn/protocol/verifiable-random-functions.md) that ensures randomness and decentralization, produces a new micro block. If a validator fails to produce a block, the remaining validators can agree on a skip block to maintain the blockchain's continuity. The structure of a micro block is divided into three parts: **header**, **body**, and **justification**.

### Micro Header

| **Field** | **Data Type** | **Description** |
| --- | --- | --- |
| `network` | `NetworkId` | The network ID associated with the block, such as Mainnet or Testnet |
| `version` | `u16` | The block's version number. A change in the version number implies a hard fork |
| `version` | `u16` | The block's version number. A change in the version number implies a hard fork. It can currently only be 1. |
| `block_number` | `u32` | The number of the block, representing its height in the blockchain |
| `timestamp` | `u64` | The block's Unix time in milliseconds, indicating when the block was produced |
| `timestamp` | `u64` | The block's Unix creation timestamp in milliseconds, indicating when the block was produced |
| `parent_hash` | `Blake2bHash` | The hash of the preceding block's header (micro or macro). This ensures a direct link to its predecessor |
| `seed` | `VrfSeed` | The BLS signature derived from the seed of the previous block, using the validator key of the block producer |
| `extra_data` | `Vec<u8>` | Space reserved for arbitrary data (currently unused) |
| `extra_data` | `Vec<u8>` | Data freely choosable by the producing validator, the default client leaves it empty |
| `state_root` | `Blake2bHash` | The root of the Merkle tree representing the blockchain state, acting as a commitment to the current state |
| `body_root` | `Blake2sHash` | The root of the Merkle tree representing the body of the block, serving as a commitment to its content |
| `diff_root` | `Blake2bHash` | The root of the trie diff tree proof, authenticating the state changes between blocks |
| `history_root` | `Blake2bHash` | The root of a Merkle Mountain Range covering all transactions in the current epoch |
| `history_root` | `Blake2bHash` | The root of a Merkle Mountain Range covering all transactions in the current epoch up until the current block|
| `cached_hash` | `Option<Blake2bHash>` | The cached hash of the block header, stored temporarily for performance optimization and not transmitted over the network |

### Micro Body
Expand All @@ -38,7 +38,7 @@ Micro blocks are the blocks for processing transactions on the Nimiq PoS blockch
| **Field** | **Data Type** | **Description** |
| --- | --- | --- |
| `Micro(Ed25519Signature)` | `Ed25519Signature` | The block producer's signature. This is used as the justification when the block is produced within the expected time |
| `Skip(SkipBlockProof)` | `SkipBlockProof` | Contains the aggregated signatures of validators for a skip block. Used as justification when the block isn't produced within the expected time |
| `Skip(SkipBlockProof)` | `SkipBlockProof` | Contains the aggregated BLS signatures of validators for a skip block. Used as justification when the block isn't produced within the expected time |

Only one of these fields is used at a time as justification, depending on whether the block is produced within the expected timeframe or not.

Expand All @@ -59,17 +59,17 @@ Macro blocks need +2/3 of consensus from the validator list to be confirmed, ens
| `network` | `NetworkId` | The network ID associated with the block, such as Mainnet or Testnet |
| `version` | `u16` | The block's version number. Changing this implies a hard fork |
| `block_number` | `u32` | The number of the block, representing its height in the blockchain |
| `round` | `u32` | The specific round in which this block was proposed |
| `timestamp` | `u64` | The Unix timestamp (in milliseconds) indicating when the block was produced |
| `parent_hash` | `Blake2bHash` | The hash of the preceding block's header (can be either micro or macro) |
| `round` | `u32` | The specific tendermint round in which this block was proposed |
| `timestamp` | `u64` | The Unix creation timestamp (in milliseconds) indicating when the block was produced |
| `parent_hash` | `Blake2bHash` | The hash of the preceding block's header (can only be micro) |
| `parent_election_hash` | `Blake2bHash` | The hash of the header from the previous election macro block |
| `interlink` | `Option<Vec<Blake2bHash>>` | A vector of hashes linking to previous macro blocks at defined intervals. This allows nodes to verify past blocks efficiently without needing to traverse the entire chain |
| `interlink` | `Option<Vec<Blake2bHash>>` | A vector of hashes linking to previous election blocks with epoch numbers ending in *n* zeros in binary representation. This allows nodes to verify past blocks efficiently without needing to traverse the entire chain |
| `seed` | `VrfSeed` | The BLS signature derived from the seed of the previous block, using the validator key of the block proposer |
| `extra_data` | `Vec<u8>` | Space reserved for arbitrary data (currently unused) |
| `state_root` | `Blake2bHash` | The Merkle root representing the blockchain state, acting as a commitment to the current state |
| `body_root` | `Blake2sHash` | The Merkle root representing the body of the block, serving as a commitment to its content |
| `diff_root` | `Blake2bHash` | The root of the trie diff tree proof, which authenticates the state transitions or changes between blocks |
| `history_root` | `Blake2bHash` | The root of a Merkle Mountain Range covering all transactions that occurred in the current epoch |
| `history_root` | `Blake2bHash` | The root of a Merkle Mountain Range covering all transactions that occurred in the current epoch up until this block |
| `validators` | `Option<Validators>` | Information about the upcoming validator list. Present only in election macro blocks |
| `next_batch_initial_punished_set` | `BitSet` | A bitset representing validator slots that are banned from producing blocks in the next batch due to misbehavior |
| `cached_hash` | `Option<Blake2bHash>` | A cached hash of the block header, used to optimize performance. Not transmitted over the network |
Expand All @@ -78,14 +78,14 @@ Macro blocks need +2/3 of consensus from the validator list to be confirmed, ens

| **Field** | **Data Type** | **Description** |
| --- | --- | --- |
| `transactions` | `Vec<RewardTransaction>` | Contains the reward-related transactions of this block, distributing rewards to validators |
| `transactions` | `Vec<RewardTransaction>` | Contains the reward transactions of this block, distributing block rewards and transaction fees of the current batch to validators |

### Macro Justification

| **Field** | **Data Type** | **Description** |
| --- | --- | --- |
| `round` | `u32` | The specific round in which the block was accepted. This is used to verify that the signature corresponds to the correct round |
| `sig` | `MultiSignature` | The aggregated signature of the validators’ precommit votes for the block, confirming validator consensus |
| `round` | `u32` | The specific tendermint round in which the block was accepted. This is used to verify that the signature corresponds to the correct round |
| `sig` | `MultiSignature` | The aggregated BLS signature of the validators’ precommit votes for the block, confirming validator consensus |

The figure below illustrates how a macro block and a micro block are linked. Each block, whether macro or micro, is directly connected to its predecessor through the **parent hash** and the **random seed**.

Expand All @@ -95,8 +95,8 @@ The figure below illustrates how a macro block and a micro block are linked. Eac

The Nimiq blockchain is structured into several subsets of blocks called epochs and batches.

- **Batches**: A batch consists of a fixed number of **micro blocks** produced one after the other. Each batch ends with a **checkpoint** macro block, which finalizes the transactions included in the preceding micro blocks.
- **Epochs**: An epoch is a set of multiple batches together. Each epoch ends with an **election** macro block, which not only finalizes the transactions in the preceding batch but also updates the validator list of the entire epoch.
- **Batches**: A batch consists of 59 **micro blocks** produced one after the other. Each batch ends with a **checkpoint** macro block, which finalizes the transactions included in the preceding micro blocks. Since the micro blocks are supposed to be spaced 1 second apart, a batch is expected to take 1 minute.
- **Epochs**: An epoch is a set of 1440 batches together. Each epoch ends with an **election** macro block, which not only finalizes the transactions in the preceding batch but also updates the validator list of the entire epoch. Since a batch is expected to take about 1 minute, 1440 batches are expected to take 12 hours.

<img class="object-contain max-h-[max(300px)]" src="/assets/images/protocol/block-struct-3.png" alt="blockchain structure" />

Expand Down
12 changes: 6 additions & 6 deletions learn/protocol/validators/skip-blocks.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,24 @@ Skip blocks are canonical and fully recognized as part of the main chain. Once a

### Skip Block and Micro Block Differences

Skip blocks are a special type of micro block, but because they don’t hold transactions, there are some key structural differences. Below are the main differences between a skip block and a regular micro block:
Skip blocks are a special type of micro block, but because they don’t hold transactions, there are some key differences. Below are the main differences between a skip block and a regular micro block:

| **Feature** | **Skip Block** | **Micro Block** |
| --- | --- | --- |
| **Transactions** | None – skip blocks contain no transactions | Contains transactions that update the blockchain state |
| **Body** | Empty – skip blocks have no transaction or equivocation proof data | Contains transaction data and possibly equivocation proofs |
| **Body Root** | Empty – since the body is empty, the `body_root` field in the block header is also empty | Contains the Merkle root of the transactions |
| **Timestamp** | Derived from the previous block’s timestamp plus a timeout (~ 10 seconds) | Generated based on the block’s production time by the assigned producer |
| **Timestamp** | Derived from the previous block’s timestamp plus a fixed duration (4 seconds) | Generated based on the block’s production time by the assigned producer |
| **Extra Data** | Must be empty to signify its status as a skip block | Can include additional data as required by the transactions or block producer |
| **VRF Seed** | Inherents the VRF from the previous micro block without introducing new randomness | A new VRF seed is generated by the block producer introducing new randomness |
| **VRF Seed** | Inherits the VRF from the previous micro block without introducing new randomness | A new VRF seed is generated by the block producer introducing new randomness |
| **Justification** | Aggregated signatures from multiple validators | Single signature from the assigned producer |
| **Producer** | No specific producer; multiple validators attest to the skip block | Block producer selected to produce the block |

<img class="object-contain max-h-[max(80vh,220px)]" src="/assets/images/protocol/skip-micro.png" alt="skip block comparison to micro blocks" />

### How the Skip Block is Added?
### How is the Skip Block Added?

A skip block is an agreement among validators to confirm they did not see a micro block. The block’s justification consists of the aggregated signatures from the validators. The process goes as follows:
A skip block is an agreement among validators to confirm they did not see a micro block in the expected timeframe. The block’s justification consists of the aggregated signatures from the validators. The process goes as follows:

1. The elected validator fails to produce a micro block within the expected timeframe
2. Upon noticing the missing block, any validator can create a skip block locally
Expand All @@ -40,4 +40,4 @@ A skip block is an agreement among validators to confirm they did not see a micr

### Validator Penalty for Misbehavior

A delay in the block production is considered a minor offense. When a validator fails to produce a micro block, the associated slot is marked to not receive rewards, which are burned as a penalty. This delay also results in the deactivation of the validator slot, although it can reactivate itself after one block. For more information on this misbehavior, see the [punishments document](/learn/protocol/punishments.md#block-production-delay).
A delay in the block production is considered a minor offense. When a validator fails to produce a micro block in time, the associated slot is marked to not receive rewards, which are burned as a penalty. This delay also results in the deactivation of the validator slot, although it can reactivate itself after one block. For more information on this misbehavior, see the [punishments document](/learn/protocol/punishments.md#block-production-delay).

0 comments on commit 75f75d7

Please sign in to comment.