This article explores the Geth codebase to demystify Ethereum's "world state" and its architectural components.
Introduction
This is Part 4 of the "EVM Deep Dive" series. In Part 3, we examined contract storage mechanics. Here, we’ll explore how individual contract storage integrates into Ethereum’s broader "world state." We’ll dissect Ethereum’s architecture, data structures, and the internal workings of the Go Ethereum (Geth) client.
Ethereum Architecture Overview
Ethereum’s architecture comprises layered data structures, starting with block headers and cascading down to contract storage slots. Below is a simplified breakdown:
Block Header Components
Each block header includes critical fields that anchor Ethereum’s state:
- Prev Hash: Keccak hash of the parent block.
- State Root: Merkle root hash of the entire state post-transactions (key focus).
- Transaction Root: Merkle root of all transactions in the block.
- Receipt Root: Merkle root of transaction receipts.
- Other Fields: Nonce, Timestamp, Gas Limit/Load, etc.
👉 Explore Ethereum block anatomy
State Root: The Gateway to World State
The State Root is a Merkle root hash derived from a Merkle Patricia Trie (MPT) that maps Ethereum addresses to account states. Key points:
- Addresses (hashed) act as keys.
- Account States (RLP-encoded) are values.
- Any change in account data (e.g., balance) alters the State Root.
Ethereum Account Structure
Each account (e.g., 0x...) stores:
- Nonce: Transaction count (EOA) or contract creations (CA).
- Balance: Wei held by the address.
- CodeHash: Hash of contract bytecode (empty for EOAs).
- StorageRoot: Merkle root of contract storage (details below).
StorageRoot: Contract Storage Trie
The StorageRoot is another MPT, but it maps:
- Keys: Storage slots (e.g.,
slot0). - Values: Data in each slot (e.g.,
0x123...).
How SSTORE & SLOAD Work
SSTORE (Write):
- Pops
keyandvaluefrom the stack. - Updates
dirtyStoragein thestateObject(intermediate state). - Finalized via
StateDB.Commit()(updates StorageRoot).
- Pops
SLOAD (Read):
- Pops
keyfrom the stack. - Checks
dirtyStorage→pendingStorage→originStorage(in order). - Returns the latest value for the slot.
- Pops
👉 Dive into Geth’s state transitions
Geth Implementation Deep Dive
Key Structures
- StateDB: Manages trie databases and account states.
- stateObject: Represents an account mid-transaction.
- StateAccount: RLP-encoded account data (fields: Nonce, Balance, etc.).
Initializing a New Account
StateDB.createObject()generates astateObjectwith an emptyStateAccount.- SSTORE writes propagate through
dirtyStorage→pendingStorage→originStorage. - StorageRoot updates occur during
StateDB.Commit().
FAQs
1. What is the State Root?
The State Root is a Merkle root representing the entire Ethereum state (all accounts) after executing a block’s transactions.
2. How does contract storage connect to the State Root?
- Each contract’s
StorageRoot(in itsStateAccount) links to a Merkle Patricia Trie of its storage slots. - Changes to slots alter the
StorageRoot, thus affecting theState Root.
3. Why does SLOAD check dirtyStorage first?
dirtyStorage holds the most recent slot values during transaction execution, ensuring reads reflect uncommitted changes.
4. What triggers a StorageRoot update?
StateDB.Commit() finalizes writes by updating the trie database, recalculating the StorageRoot and State Root.
Conclusion
Ethereum’s "world state" is a hierarchical data structure anchored by the State Root and StorageRoot. Understanding these components clarifies how contract storage integrates into the broader blockchain state. Stay tuned for Part 5, where we’ll explore CALL and DELEGATECALL opcodes!
Further Reading:
### SEO Notes:
- **Keywords**: EVM, Geth, World State, State Root, StorageRoot, SSTORE, SLOAD, Merkle Patricia Trie.