This part of the series dives into section 4.3 of the Yellow Paper, that elaborates the structure of blocks.
If you haven't yet, go through Part 0 of this series to get conventions right.
Block
A block,
- Block Header,
- List of transactions,
included in the block - A deprecated property,
which prior to Paris fork, represented headers of blocks whose parents were present block's parent's parent (a.k.a ommers) - A collection of validator withdrawals
pushed by consensus layer
Hence, a block
The header
( ): Hash of parent block's header. ( ): Hash that is now set to constant, since deprecation. ( ): Beneficiary address priority fee from all transactions in this block. ( ): Hash of root of state trie after all transaction in block are finalized. ( ): Hash of root of trie containing all transactions in this block. ( ): Hash of root of trie containing all receipts corresponding to each transaction in this block. ( ): Bloom filter created from indexable information in logs of transaction receipts of transactions in this block. (See bloom filter section). ( ): A scalar value representing difficulty of this block. ( ): Number of all ancestor blocks of this block. ( ): Current limit of gas expenditure per block. ( ): The total gas used by all transactions in this block. ( ): Unix time when this block was created. ( ): An arbitrary byte array containing data relevant to this block. This must be 32 bytes or fewer. ( ): The latest RANDAO mix (a pseudorandom value) after finalization of previous block. RANDAO is a mechanism for generating randomness for the network. See here for detail. ( ): A 64-bit value which now deprecated and set to constant 0 due to replacement of proof-of-work to proof-of-stake. ( ): Amount of wei burned per unit of gas consumed in this block. ( ): Hash of root of trie populated with withdrawals by validators.
Transaction Receipts
The transaction receipts correspond to each transaction in a block and contains information related to execution of the transaction. Given a block
- Type of transaction. - Status code of transaction. - Cumulative gas used in the block immediately after this transaction happened. - Set of logs created (aka events emitted) through execution of this transaction. - The bloom-filter composed of the logs.
Hence it can be denoted as:
And, like other entities, corresponding collapse function for a receipt,
The values are restricted/belong to their respective sets:
Notice that
- Logger's address (contract that emitted event log) - Series of log 32-byte topics, . You might know these as indexed parameters in an event. This could possibly be empty. - Some number of bytes of data. The un-indexed parameters of an event go into these.
This is saying same as:
where
Bloom Filter
The
I highly recommend you to read up more about Bloom filters here before proceeding this section.
Note: Only event logs marked "indexed" (in Solidity) are included in bloom filter. This is why you can only filter events data by these "indexed" event parameters.
The paper formally defines the Bloom filter function,
Let's decode it.
The
where
Now onto the working of
This 2048 bits length output
Which of the 3 bits to set is defined by
- First it keccak-256 hashes the byte sequence
i.e. . - Then takes the first three pairs of bytes (byte pairs at indices
) from the hash, . - And then from each pair of bytes at indices
( ), it takes the low-order 11 bits out of 16 bits (each byte pair is 16 bits). - Each of these 11-bit value (corresponding to each of 3 byte pairs) is subtracted from 2047 (highest 11-bit value in decimal) to output a set of 3 indices ranging from 0 to 2047.
- These are the obtained indices at which bit is set to 1 in
byte sequence from .
Mathematically, the paper defines a helper function
As described earlier, it extracts 11 bits from two bytes (
Paper also defined a rather simple
And this is how bloom-filters are calculated for logs.
Block Validity
A block's validity is satisfied if and only if certain conditions are met:
- Block's ommers field
must be empty (post Paris fork).
- The new root of state trie, must be equal to root of the trie derived from new state after transactions of this block,
are finalized at state, .
where
Recall from
- The
must be the root of the trie which is derived from pairwise RLP-encoding withdrawals:
where
- The block header
, must be equal to root of trie which is derived from RLP-encoding of all transactions, in the block. The transaction, at index , (= ) is RLP-encoded based on transaction its type, .
where function
Note that index
- Likewise the
, is derived from RLP-encoding of receipts which depends of receipt transaction type, :
where function
must bitwise of all bloom filters, derived from each receipt.
Combining all of the above, a block's validity is constrained by:
Futhermore, paper defines the equation,
If
Serialization
The paper lays out functions
where
with
The header component values belong to respective sets:
where, as already defined in convention,
Block Header Validity
The parent block of block,
i.e. the parent of
The block number,
The base fee per gas
The expected value of base fee per gas is defined by function
Remember
You may know that gas fees of the Ethereum network adjusts in response to the conjestion of transactions - more transactions being broadcasted means more fees. More transactions also mean more gas being consumed in a block i.e.
This basically conveys that the adjustments to the fee
The first case,
The second case,
The next two cases (
When gas consumed in parent block
Precisely according to paper
Since Ethereum is not a dead chain, in almost all cases
But technically,
In set notation, above is same as saying:
Let's assume instead of being proportional,
To avoid this situation the effect of gas consumed on mechanism is dampened. This is done by introducing a global constant
Instead of setting
Now, even if
That explains the base fee adjustment mechanism. The logic for the last case
A minor difference is for case
The canonical gas limit
Notice that
The block timestamp
From Paris fork (change in consensus mechanism from proof of work to proof of stake) deprecated multiple block header properties:
, has been replanced by , is set to a constant: is set to a constant: is set to a constant:
Finally, we can define validity of a block header,
- Gas used must be less than or equal to the gas limit:
must be constrained by must be constrained by- Block number must be equal to parent block number incremented by 1:
- The
field must be 32 bytes at most in size: - The block's base gas fee must be determined as defined in
: - Deprecate fields as defined in
, and must be determined Beacon Chain (consensus):
Combining all constraints defines
And that wraps up the blocks! Up next we see Gas and Payment.