The anatomy of the block (head) Pt. 1

James Olsen
5 min readDec 1, 2021

--

So you have finished reading your medical textbook for “The anatomy of the body” and you are feeling disappointed. Sure, there was plenty of chapters talking about lungs, brains, livers, and those other peculiar body parts, but where are the chapters about blocks (in Ethereum)? Your professor kept on looking at you quizzically when you asked at every lecture what happens anatomically when a child block refers to an uncle block, and your parents got mad when you said you wanted to drop out of University for this reason.

Blocky the dancing block — known for his wild nights on town after classes…

Well, now you can be at ease. You no longer need to pay your (block’s) weight in gold for your medical degree just on the hope that you will finally understand why blocks have gas. In this article I am going to teach you everything you need to know about the anatomy of a block!

The musculoskeletal structure of the block. Credit to https://www.lucassaldanha.com/ethereum-yellow-paper-walkthrough-2/ for image.

Don’t let it go to your head…

Each block added to a blockchain has a lot going on in it. Most interesting to most people is the transactions stored in a block, but these are also the parts that make most sense. It is the headers of the block, filled so deeply with endless strings of 1’s and 0’s, that are the enigmatic commanders of the fate of blocks and the blockchain as a whole. To understand this in its entirety you will need to brush up on your Merkle-Patricia tree knowledge. In Ethereum there are 15 fields for the header in total. Also included in each block are an additional 15 fields for each ommer/uncle block referenced (up to two) that are copies of the headers of these specific blocks — though these ommer fields are specifically stored in the body of the block and not the header..

  1. parentHash: Most commonly referred to as prevHash. The 256-bit hash belonging to the parent of the current block.
  2. ommersHash: 256-bit hash of the headers of the (up to) two ommer/uncle blocks referred to by the current block.
  3. beneficiary: The 160-bit address that all transaction fees (the currency paid by users to have their transactions included) will be dedicated to given it is a) mined/validated, or b) referred to as an ommer/uncle block.
  4. stateRoot: This is the head node of the state trie (otherwise referred to as the world state trie) which keeps track of all accounts (e.g. wallet addresses) and their state after all transactions in and preceding the current block have been executed. Is stored in 256-bits by use of a Merkle-Patricia tree that can consolidate all this information into one node.
  5. transactionsRoot: This is the head node of the transaction trie which keeps track of all transactions in the current block. Is stored in 256-bits by use of a Merkle-Patricia tree that can consolidate all information into one node.
  6. receiptsRoot: This is the head node of the transaction receipt trie (otherwise referred to as the receipt trie) which keeps track of all outcomes of the execution of transactions (e.g. which accounts have had changes in balance) within the current block. Is stored in 256-bits by use of a Merkle-Patricia tree that can consolidate all information into one node.
  7. logsBloom: Information about the transactions stored within a block in a manner that can quickly be searched through (i.e. to discover if there are any transactions of interest within a block) while requiring only 256-bits worth of space. Relies on the bloom filters data structure.
  8. difficulty: Scalar value representing the difficulty of mining the current block — dependent on the difficulty of the parent block and the timestamp. Often used to indicate the number of “leading zeros” that must be found in the current block’s hash to be valid.
  9. number: The number of ancestor blocks for the current block represented with a scalar value.
  10. gasLimit: Limitation on the total gas that may be used by the current block, represented by a scalar value.
  11. gasUsed: Total gas that was used by the current block, represented by a scalar value.
  12. timestamp: Reasonable estimation of the time when the block was created using the output of the UNIX time() function as a scalar value. This value can be expected to be inaccurate by a number of seconds or more.
  13. extraData: Field that can be used by the creator of the current block to include information relevant to said block; up to a maximum of 256-bits in size.
  14. mixHash: Most commonly referred to as the hash. The 256-bit hash belonging to the current block. Must meet the difficulty constraints of the current block to ensure that the block is valid (i.e. this proves that the sufficient “work” has been done).
  15. nonce: Value chosen by a miner to attempt to modify the mixHash to meet the difficulty constraints of the current block; represented with 64-bits.
In-depth description of the various trie referenced in the block. Credit to https://www.lucassaldanha.com/ethereum-yellow-paper-walkthrough-2/ for image.

As a quick guide on the trie we have been referring to throughout the block header fields, they are essentially Merkle-Patricia trees. All new data is added to leaf nodes in the bottom row of this tree, and these data nodes are subsequently hashed in pairs with each other data node, step-by-step, until there remains one output which is the root node of that trie. New data is added to the bottom row of the tree from left-to-right, and each new piece of added data will change a significant number of hashed nodes located above said data in the tree (as well as the root node).

In total the header of a block (prior to compression) requires 284 bytes for storage as well as an additional five scalar fields that could take up as little or as much space as required. Each block also requires (prior to compression) up to an additional 568 bytes and ten scalar fields for each ommer block referred to. Given the current average block size (as of 18/08/21) is 70 kilobytes, this means that anywhere between 0.4% and 1.2% (theoretically) of a block could be dedicated to non-transaction data assuming no compression occurs.

How low can you go…?

Ethereum employs a simple compression algorithm for blocks that only compresses strings of 0’s, meaning on average a lot of data remains for a block remains behind even after compression. They have taken the approach of avoiding using any special use cases to save on data to ensure the most informative presentation of said data, free of abstraction.

But wait! There’s more…

…you cried, comfy in bed realising they you still had a chapter to read before tomorrow that you had entirely forgotten about. Follow me, and together we shall investigate what goes on in those pesky transactions within each block in part two!

  1. https://ethereum.github.io/yellowpaper/paper.pdf
  2. https://medium.com/@eiki1212/ethereum-state-trie-architecture-explained-a30237009d4e
  3. https://medium.com/@eiki1212/ethereum-transaction-structure-explained-aa5a94182ad6
  4. https://eth.wiki/fundamentals/design-rationale
  5. https://ethereum.org/en/developers/docs/transactions/
  6. https://docs.ethhub.io/ethereum-roadmap/ethereum-2.0/eth-2.0-phases/
  7. https://www.lucassaldanha.com/ethereum-yellow-paper-walkthrough-2/
  8. The anatomy of the block (head) Pt. 2

--

--