State in Ethereum

Merkle Trees

(Original: https://docs.tingchain.org/ting-application-chain-ecosystem/developers/concepts/state-in-ethereum#merkle-trees)

Before discussing the main data objects in Ethereum, we need to go over what Merkle trees are, and what are the properties that make them useful.

A Merkle tree is a tree data structure, where the leaf nodes contain the hash of a block of data and the non-leaf nodes contain the hash of its children nodes.

In a Merkle tree, any change to the underlying data causes the hash of the node referring to the data to change. Since each parent node hash depends on the data of its children, any change to the data of a child node causes the parent hash to change. This happens to each parent node up to the root node. Therefore, any change to the data at the leaf nodes causes the root node hash to change. From this, we can derive two important properties:

  • We don't need to compare all the data across the leaf nodes to know if they have the same data. We can just compare the root node hash.

  • If we want to prove that specific data is part of the tree, we can use a technique called Merkle proofs. We won't dive into details here but it is an easy and effective way to prove that a piece of data is in the Merkle tree.

The first property is important because it makes it possible to store only a hash of the root node to represent the data at that point in time. This means we only need to store the root hash of the tree representing the block on the blockchain (as opposed to storing all the data in the blockchain) and still keep the data immutable.

World State

(Original: https://docs.tingchain.org/ting-application-chain-ecosystem/developers/concepts/state-in-ethereum#world-state)

The world state is a mapping between addresses (accounts) and account states.

The world state is not stored on the blockchain, but the Yellow Paper states it is expected that implementations store this data in a trie (also referred to as the state database or state trie). The world state can be seen as the global state that is constantly updated by transaction executions.

All the information about Ethereum accounts lives in the world state and is stored in the world state trie. If you want to know the balance of an account, or the current state of a smart contract, you query the world state trie to retrieve the account state of that account. We’ll describe how this data is stored shortly.

Account State

(Original: https://docs.tingchain.org/ting-application-chain-ecosystem/developers/concepts/state-in-ethereum#account-state)

In Ethereum, there are two types of accounts: External Owned Accounts (EOA) and Contract Accounts.

An EOA account is an account that regular users have, that they can use to send Ether to one another and deploy smart contracts with.

A contract account is an account that is created when a smart contract is deployed. Every smart contract has its own Ethereum account.

The account state contains information about an Ethereum account. For example, it stores how much Ether an account has, and the number of transactions sent by the account. Each account has an account state.

Fields in the account state:

  • nonce – Number of transactions sent from this address (if this is an External Owned Account - EOA) or the number of contract creations made by this account

  • balance – Total Ether (in Wei) owned by this account

  • storageRoot – Hash of the root node of the account storage trie

  • codeHash – For contract accounts, the hash of the EVM code of this account. For EOAs, this will be empty.

All fields (except the codeHash) are mutable. For example, when one account sends some Ether to another, the nonce will be incremented, and the balance will be updated to reflect the new balance.

Because codeHash is immutable, if you deploy a contract with a bug, you can't update the same contract β€” you must deploy a new contract. This is why testing and best practices for Solidity are important.

The Account Storage trie is where the data associated with an account is stored. This is only relevant for Contract Accounts; for EOAs the storageRoot is empty, and the codeHash is the hash of an empty string.

Transactions

(Original: https://docs.tingchain.org/ting-application-chain-ecosystem/developers/concepts/state-in-ethereum#transactions)

Transactions are what make the state change from the current state to the next state. In Ethereum, we have three types of transactions:

1

Transactions that transfer value between two EOAs

Example: change the sender and receiver account balances.

2

Transactions that send a message call to a contract

Example: set a value in a smart contract by sending a message call that executes a setter method.

3

Transactions that deploy a contract

Creates a contract account when a smart contract is deployed.

circle-info

Clarification: Technically, the first two types are the same β€” both are message-call transactions that affect an account state (EOA or contract). It's often easier to think of them as distinct types.

Transaction fields:

  • nonce – Number of transactions sent by the account that created the transaction

  • gasPrice – Value (in Wei) paid per unit of gas for computation costs

  • gasLimit – Maximum amount of gas to be used while executing this transaction

  • to

    • If transferring Ether: the recipient EOA address

    • If sending a message to a contract: the contract address

    • If creating a contract: this value is empty

  • value

    • If transferring Ether: amount in Wei to transfer

    • If sending a message to a contract: amount of Wei payable by the receiving contract

    • If creating a contract: amount of Wei added to the created contract's balance

  • v, r, s – Values used in the cryptographic signature of the transaction to determine the sender

  • data (for value transfer and message calls) – Input data of the message call (e.g., method identifier and parameters when calling a contract function)

  • init (for contract creation) – The EVM code used for initialization of the contract

All transactions in a block are stored in a trie. The root hash of this trie is stored in the block header.

Blocks

(Original: https://docs.tingchain.org/ting-application-chain-ecosystem/developers/concepts/state-in-ethereum#blocks)

The block is divided into the block header and the block body.

  • The block header is the blockchain part of Ethereum. It contains the hash of its predecessor block (parent block), building a cryptographically guaranteed chain.

  • The block body contains a list of transactions included in this block and a list of uncle (ommer) block headers.

Block header fields:

  • parentHash – Hash of the previous block header

  • ommersHash – Hash of the uncle blocks headers part of the block body

  • beneficiary – Ethereum account that will get fees for mining this block

  • stateRoot – Hash of the root node of the world state trie (after all transactions are executed)

  • transactionsRoot – Hash of the root node of the transactions trie (this trie contains all transactions in the block body)

  • receiptsRoot – Hash of the root node of the transaction receipts trie

  • logsBloom – Bloom filter used to find whether logs were generated by transactions in this block

  • difficulty – Difficulty level of this block (measure of how hard it was to mine)

  • number – Block height (genesis block has number zero)

  • gasLimit – Maximum gas that can be used by transactions included in the block

  • gasUsed – Sum of gas cost of each transaction in the block

  • timestamp – Unix timestamp when the block was created (note: not fully trustable for decentralized timing)

  • extraData – Arbitrary byte array a miner can include

  • mixHash – Hash used to verify proper mining (related to Ethash)

  • nonce – Value used to verify that a block has been mined properly

Recap

(Original: https://docs.tingchain.org/ting-application-chain-ecosystem/developers/concepts/state-in-ethereum#recap)

Ethereum uses several tries to represent state and transactions. The following stepper summarizes the main tries and objects:

1

World state trie

Contains the mapping between addresses and account states. The hash of the root node (stateRoot) is included in a block header to represent the world state at that block. There is one world state trie.

2

Account storage trie

Contains the data associated with a smart contract. The hash of its root (storageRoot) is included in the account state. There is one account storage trie per account (for contract accounts).

3

Transaction trie

Contains all transactions included in a block. The hash of its root (transactionsRoot) is included in the block header. There is one transaction trie per block.

4

Transaction receipt trie

Contains all transaction receipts for transactions included in a block. The hash of its root (receiptsRoot) is included in the block header. There is one transaction receipts trie per block.

Objects covered:

  • World state: the mapping between addresses and account states (the global state of Ethereum).

  • Account state: stores an account's state and the storageRoot for its account storage trie.

  • Transaction: represents a state transition (funds transfer, message call, or contract deployment).

  • Block: links to the previous block (parentHash) and contains transactions that yield the new state; includes stateRoot, transactionsRoot, and receiptsRoot.

Credits

(Original: https://docs.tingchain.org/ting-application-chain-ecosystem/developers/concepts/state-in-ethereum#credits)

This walkthrough of Ethereum's Yellow Paper content was originally posted by Lucas Saldanha on his personal blog: https://www.lucassaldanha.com/author/lucas-saldanha/

πŸ“œ Resources

Last updated