以太坊 Yellow Paper 工程師視角導讀:從規格到實作的完整解析手冊
Yellow Paper 是以太坊的形式化規格文件,本文以工程師能理解的方式導讀其核心內容。涵蓋世界狀態、區塊結構、交易執行、EVM 執行模型、Gas 成本定義等章節的深度解析,配合 go-ethereum 原始碼對照,幫助讀者理解『為什麼』而非僅止於『是什麼』。適合想深入理解以太坊底層運作的進階開發者與研究者。
以太坊 Yellow Paper 工程師視角導讀:從規格到實作的完整解析手冊
老實說,第一次翻開 Yellow Paper 的時候,我以為自己打開了什麼奇怪的論文。那符號多到眼花撩亂,Σ、∈、→ 全部混在一起,感覺像在看埃及象形文字。
但後來我發現一件事:如果你真的想把以太坊搞懂,而不是停在「會用」的層次,Yellow Paper 是繞不過去的。很多 Medium 文章說「以太坊如何運作」,但只有 Yellow Paper 會告訴你「以太坊必須如何運作」。
這篇文章是我的學習筆記,用工程師能理解的方式,帶你走一遍 Yellow Paper 的核心內容。目標不是讓你背公式,而是讓你搞懂「這個符號到底在表達什麼」。
一、Yellow Paper 是什麼?
Yellow Paper 是以太坊的形式化規格文件,由 Gavin Wood 撰寫(2014 年),現在由以太坊基金會維護。它是用數學符號描述以太坊狀態機的文件。
官方定義(翻譯成人話):
「這份文件定義了以太坊的執行模型。
包括:區塊結構、共識機制、交易執行、狀態轉換函數。」
翻譯:
「這東西告訴你:以太坊的 state 是怎麼從 A 變成 B 的。
以及,什麼情況下 transaction 會被接受或拒絕。」
為什麼叫 Yellow Paper?因為比特幣的白皮書(White Paper)是用白紙,而以太坊的文件封面是黃色的——就這樣,沒有更深奧的意思。
1.1 讀 Yellow Paper 的正確姿勢
我讀了五遍 Yellow Paper,總結出來的竅門:
準備工具:
1. 一杯咖啡(很濃的那種)
2. Etherscan(用來對照實際區塊資料)
3. go-ethereum 原始碼(用來對照實作)
4. 便利貼(標記看不懂的地方)
閱讀順序(我的建議):
1. 先看 Section 2(區塊、狀態、交易)
2. 再看 Section 8(EVM)
3. 然後 Section 4(交易執行)
4. 最後 Section 10(共識)
千萬不要:
❌ 從頭讀到尾
❌ 一次性讀完全部
❌ 試圖搞懂每一個數學符號
二、核心概念:狀態、世界狀態、帳戶
Yellow Paper 的起點是世界狀態(World State)。這是以太坊區塊鏈的核心。
2.1 符號定義(Section 2.1)
σ ≡ 世界狀態(World State)
σ 是一個 mapping:address → account_state
σ[addr] ≡ 某地址的帳戶狀態
= (nonce, balance, storage_root, code_hash)
address ≡ 160 位元的識別符
用 Python 翻譯:
# 這是以太坊世界狀態的簡化模型
class Account:
nonce: int # 交易計數器(防止 replay 攻擊)
balance: int # ETH 餘額(單位:Wei)
storage_root: bytes # storage trie 的 Merkle root
code_hash: bytes # 合約程式碼的 hash(EOA 是空 bytes)
# 世界狀態就是:address → Account
world_state: dict[bytes20, Account]
重要理解:帳戶狀態存在 Merkle Patricia Trie 裡,不是存在區塊裡。區塊只存 trie 的 root hash。這就是所謂的「状态承诺」(State Commitment)。
2.2 兩種帳戶
┌─────────────────────────────────────────────────────────────┐
│ 外部擁有帳戶 (EOA) │
├─────────────────────────────────────────────────────────────┤
│ - 由私鑰控制的帳戶 │
│ - 沒有關聯的程式碼 │
│ - 可以發起交易 │
│ σ[addr].code_hash = EmptyCodeHash (= Keccak256(∅)) │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ 智能合約帳戶 (CA) │
├─────────────────────────────────────────────────────────────┤
│ - 由程式碼控制 │
│ - 有關聯的程式碼 │
│ - 只能響應收到的交易 │
│ - 可以建立新合約、呼叫其他合約 │
└─────────────────────────────────────────────────────────────┘
def is_eoa(address, world_state):
"""判斷是否為外部擁有帳戶"""
code_hash = world_state[address].code_hash
return code_hash == EMPTY_CODE_HASH
def is_contract(address, world_state):
"""判斷是否為智能合約"""
code_hash = world_state[address].code_hash
return code_hash != EMPTY_CODE_HASH
三、區塊結構(Section 4.3)
3.1 區塊的數學定義
B ≡ (BlockHeader, TransactionList, UncleList)
BlockHeader ≡ (
prevBlocksHash, # ← 父區塊的 hash
ommersHash, # ← Uncle 區塊的 hash
beneficiary, # ← 礦工地址(PoW)/ 提議者(PoS)
stateRoot, # ← 交易後的世界狀態 root
transactionsRoot, # ← 交易清單的 root
receiptsRoot, # ← 交易收據的 root
logsBloom, # ← Bloom filter,用來快速搜尋 event
difficulty, # ← 區塊難度(PoW)/ 預測值(PoS)
number, # ← 區塊高度
gasLimit, # ← 區塊 Gas 上限
gasUsed, # ← 區塊實際使用的 Gas
timestamp, # ← 區塊時間戳
extraData, # ← 額外資料(最多 32 bytes)
mixHash, # ← PoW 用的 mix hash
nonce # ← PoW 用的 nonce
)
我第一次看到這個定義的時候,只有一個想法:原來區塊就是這些東西組合起來的!
實務對照:
打開 Etherscan,随便點一個區塊:
https://etherscan.io/block/19500000
你會看到:
- Block Height: 19500000
- Timestamp: 2026-03-28 12:00:00
- Transactions: 150
- Gas Used: 15,000,000 / 30,000,000
- Miner: 0x1234...abcd
- Difficulty: 5.5 PH
- Extra Data: 0x
這些全部對應 Yellow Paper 裡的 BlockHeader 欄位!
3.2 Uncle 的數學意義
Yellow Paper 定義了 Uncle 的格式:
ommerHash = Keccak256(RLP(ommerList))
Uncle 是「差一點成為主鏈區塊的分叉區塊」。在 PoW 時代,叔塊獎勵是一個有點奇怪的設計——它獎勵那些「輸掉競爭」的礦工。
為什麼要有 Uncle?
PoW 以太坊的平均區塊時間是 ~13 秒
網路延遲導致很多「合法的」區塊成為孤塊
如果沒有叔塊獎勵:
- 大礦池有優勢(因為離礦池近,孤塊率低)
- 小礦池更難生存
- 網路去中心化程度降低
有了叔塊獎勵:
- 叔塊礦工也能獲得部分獎勵
- 鼓勵礦工廣播區塊,而不是只廣播給礦池
- 提高了網路的去中心化程度
四、交易執行(Section 6)
4.1 交易類型
T ≡ (T_nonce, T_gasPrice, T_gasLimit, T_to, T_value, T_data, T_v, T_r, T_s)
其中:
T_nonce ≡ 交易計數器,防止 replay 攻擊
T_gasPrice ≡ 用戶願意支付的 Gas 單價
T_gasLimit ≡ 用戶願意支付的最大 Gas
T_to ≡ 目標地址(EOA 或 合約)
T_value ≡ 轉帳金額(單位:Wei)
T_data ≡ 調用的資料(合約方法、參數等)
T_v, T_r, T_s ≡ 交易的電子簽章
class Transaction:
nonce: int # 帳戶的交易計數
gas_price: int # Gwei 轉 Wei
gas_limit: int # 最大 Gas
to: bytes20 # 目標地址
value: int # 轉帳金額
data: bytes # 呼叫資料
v: int # 簽章 recovery id
r: int # 簽章 R 值
s: int # 簽章 S 值
def sender(self) -> bytes20:
"""從簽章還原發送者地址"""
return ecrecover(self.v, self.r, self.s)
4.2 狀態轉換函數(State Transition Function)
這是 Yellow Paper 最核心的部分。狀態轉換函數定義了:給定當前狀態 σ 和交易 T,如何得到新狀態 σ'。
σ' = Ξ(σ, T)
Ξ 就是狀態轉換函數
σ 是當前世界狀態
T 是待執行的交易
σ' 是執行後的新世界狀態
具體來說:
def state_transition(world_state, transaction):
"""
Yellow Paper 中的 Ξ 函數
步驟:
1. 驗證交易簽章
2. 扣 Gas(預扣 gas_limit × gas_price)
3. 執行交易
4. 計算實際 Gas 消耗
5. 退還多餘的 Gas
"""
# Step 1: 簽章驗證
sender = transaction.sender()
assert sender in world_state, "Sender must exist"
assert transaction.nonce == world_state[sender].nonce, "Nonce mismatch"
# Step 2: 預扣 Gas
gas_initial = transaction.gas_limit * transaction.gas_price
world_state[sender].balance -= gas_initial
# Step 3: 執行(複雜度最高的部分)
# 這裡呼叫 EVM...
success, gas_used, logs = execute_evm(
world_state,
transaction
)
# Step 4: 計算退款
gas_refund = (transaction.gas_limit - gas_used) * transaction.gas_price
# Step 5: 退還未使用的 Gas
if success:
world_state[sender].balance += gas_refund
# 燒毀 base fee(EIP-1559 後)
burn_amount = gas_used * base_fee
# miner/consolidator 獲得 tip
beneficiary_reward = gas_used * (priority_fee)
else:
# 失敗:只退還未執行的部分
world_state[sender].balance += (transaction.gas_limit - gas_used) * transaction.gas_price
return world_state
五、EVM 執行模型(Section 8)
5.1 EVM 作為狀態轉換函數
Yellow Paper 把 EVM 定義成一個狀態機:
(σ, μ, A, i) → (σ', μ', A', o)
σ ≡ 世界狀態
μ ≡ 機器狀態(PC, Stack, Memory, Gas)
A ≡ 執行環境(msg.sender, msg.value, block info...)
i ≡ 程式碼
σ' ≡ 新的世界狀態
μ' ≡ 新的機器狀態
A' ≡ 新的執行環境
o ≡ 輸出(return data)
class EVMState:
pc: int # Program Counter(指令指標)
stack: list[int] # 堆疊(最多 1024 層)
memory: bytearray # 記憶體(可擴展)
gas: int # 剩餘 Gas
storage: dict # 合約 storage
def evm_step(state: EVMState, code: bytes) -> EVMState:
"""
執行一個 EVM 指令
這就是 Yellow Paper 中 Λ 函數的作用
"""
opcode = code[state.pc]
if opcode == 0x00: # STOP
return state # 停止執行
elif opcode == 0x01: # ADD
a = state.stack.pop()
b = state.stack.pop()
state.stack.append((a + b) % 2**256)
state.pc += 1
state.gas -= G_add # 3 Gas
elif opcode == 0x02: # MUL
a = state.stack.pop()
b = state.stack.pop()
state.stack.append((a * b) % 2**256)
state.pc += 1
state.gas -= G_mul # 5 Gas
# ... 其他 opcode ...
return state
5.2 Gas 成本定義(Section 9)
Yellow Paper 用數學符號定義了每個 opcode 的 Gas 成本:
┌─────────────────────────────────────────────────────────────┐
│ 符號定義表 │
├─────────────────────────────────────────────────────────────┤
│ │
│ G_base ≡ 2 基礎操作 Gas(STOP, ADD, ...) │
│ G_verylow ≡ 3 很簡單的操作(SLT, BYTE, ...) │
│ G_low ≡ 5 乘法等操作(MUL, DIV, ...) │
│ G_mid ≡ 8 稍微複雜的操作(SDIV, MOD, ...) │
│ G_high ≡ 10 複雜操作(JUMP, JUMPI, ...) │
│ G_extcode ≡ 700 讀取代碼(SSTORE, CREATE, ...) │
│ G_balance ≡ 400 讀取餘額 │
│ G_sload ≡ 800 Storage 讀取 │
│ G_sstore ≡ 20000 新增 storage slot │
│ │
│ W_memory ≡ 3 每 word 記憶體成本 │
│ G_memory ≡ 0 基礎記憶體成本 │
│ │
└─────────────────────────────────────────────────────────────┘
# 對照 go-ethereum 的實作
# core/vm/gas.go
const (
GasQuickStep uint64 = 2
GasFastestStep uint64 = 3
GasFastStep uint64 = 5
GasMidStep uint64 = 8
GasSlowStep uint64 = 10
GasExtStep uint64 = 20
)
# core/vm/gas_table.go
func GasSStore(evm *EVM) uint64 {
if evm.StateDB.GetState(addr, key) == (common.Hash{}) {
// 新增 slot
return 20000
}
// 編輯現有 slot
return 5000
}
六、實際閱讀範例
6.1 追蹤一筆實際交易
讓我們用 Yellow Paper 的框架來分析一筆實際交易:
目標:追蹤 Uniswap 的某筆 Swap 交易
TX Hash: 0x1234...abcd
Step 1: 找到交易的基本資訊
- From: 0xABC... (EOA)
- To: 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D (Uniswap V2 Router)
- Value: 0 ETH
- Data: 0x38ed1739... (函數調用 + 參數)
Step 2: 套用狀態轉換函數
Ξ(σ_before, T) = σ_after
σ_before:
- From balance: 1.5 ETH
- From nonce: 42
- Uniswap Router storage: ...
Step 3: 執行 EVM
1. CALLER: μ_0 = msg.sender
2. CALLVALUE: μ_1 = 0
3. CALLDATALOAD: 從 calldata 讀取參數
4. SWAP: 交換堆疊元素
5. CALL: 呼叫目標合約
...
Step 4: 理解輸出
- Return data: swap 的輸出數量
- Status: Success
- Gas used: 145,000
6.2 理解 EIP-1559 的數學
Yellow Paper 裡 Base Fee 的定義是這樣的:
BASE_FEE = Parent.GasLimit * (1 - exp(-Parent.GasUsed / Parent.GasLimit))
實際上現在的實作是:
BASE_FEE = Parent.BASE_FEE * (1 + delta)
delta = (Parent.GasUsed - Parent.GasLimit * TARGET) / (Parent.GasLimit / 32)
如果 Parent 用太多 Gas → Base Fee 上升
如果 Parent 用太少 Gas → Base Fee 下降
這個公式控制了區塊空間的供需平衡。
def calculate_base_fee(parent_gas_used, parent_gas_limit, parent_base_fee,
target_gas_limit, min_base_fee):
"""
計算下一個區塊的 Base Fee
對應 EIP-1559 的實作
"""
# Gas 使用量偏離目標的程度
delta = parent_gas_used - target_gas_limit
# 每個區塊最多改變 12.5%
if delta > 0:
# 用太多 Gas,Base Fee 要漲
adjustment = max(delta // parent_gas_limit * parent_gas_limit // 8, 1)
new_base_fee = parent_base_fee + adjustment
else:
# 用太少 Gas,Base Fee 要跌
adjustment = max(delta // parent_gas_limit * parent_gas_limit // 8, 1)
new_base_fee = parent_base_fee - adjustment
# Base Fee 不能低於最低值
return max(new_base_fee, min_base_fee)
七、常見問題 Q&A
Q: Yellow Paper 和 Beige Paper 有什麼不同?
A: Beige Paper 是社群維護的「易讀版」Yellow Paper,把數學符號翻譯成 Python/Go 程式碼。適合當入門,但可能跟最新版本脫節。
Q: 需要把整篇背下來嗎?
A: 當然不需要。我讀了五遍,也不是每個公式都能背。重點是理解框架,知道去哪裡查。
Q: 讀 Yellow Paper 對寫合約有幫助嗎?
A: 有,但間接的。你不會直接用 Yellow Paper 寫合約,但你會更理解「為什麼 Gas 要這樣算」、「為什麼某個操作會貴」。這幫助你寫出更省 Gas 的程式碼。
Q: 有什麼配套資源推薦?
A:
- go-ethereum 原始碼:用來對照實作
- EVM Opcode 文件:https://www.evm.codes/
- EthGlobal 的 Workshop:實際跑一遍比看文件有效
八、結語
Yellow Paper 就像一本武林秘籍——大多數人不需要從頭到尾背下來,但每個認真想搞懂以太坊的人,都應該翻過幾遍。
讀 Yellow Paper 的最大收穫,不是記住那些數學符號,而是學會用「形式化」的方式思考。以太坊的每個行為都有明確定義,這就是區塊鏈的厲害之處——沒有模糊地帶,只有 spec 和 implementation。
有空的話,找一杯咖啡,開 Etherscan,對照著 Yellow Paper 看一筆交易。你會發現:原來這一切都是這麼優雅。
免責聲明:本網站內容僅供教育與資訊目的,不構成任何投資建議或推薦。在進行任何加密貨幣相關操作前,請自行研究並諮詢專業人士意見。所有投資均有風險,請謹慎評估您的風險承受能力。
數據截止日期:2026-03-28
標籤:technical, yellow-paper, ethereum-specification, evm, consensus, source-code, engineering
分類:technical
難度:advanced
相關文章:
- 以太坊 EVM Opcode 數學推導與 Go-ethereum 原始碼深度分析
- Go-Ethereum 核心模組原始碼導讀:共識引擎、交易池與狀態同步
延伸閱讀:
- Gavin Wood, "Ethereum: A Secure Decentralised Generalised Transaction Ledger" (Yellow Paper)
- go-ethereum GitHub: https://github.com/ethereum/go-ethereum
- EVM Codes: https://www.evm.codes/
相關文章
- go-ethereum 客戶端原始碼深度分析完整指南:從共識機制到交易池的工程實踐 — 本文從工程師視角深入分析 go-ethereum 原始碼架構,涵蓋專案組織結構、交易池(TxPool)實作、共識引擎(PoW/PoS)實現、EVM 執行引擎細節,以及與 Reth 客戶端的比較。所有程式碼範例均來自 go-ethereum v1.15 官方原始碼庫。
- 以太坊核心協議完整深度分析:EVM 執行模型、狀態 Trie 結構與帳戶生命週期 — 本文深入分析以太坊核心協議的三大支柱:帳戶模型與交易生命週期、以太坊虛擬機器(EVM)執行模型、以及狀態資料結構(Merkle Patricia Trie)。涵蓋 EOA 與智慧合約帳戶的技術實現、交易的完整生命週期、EVM 操作碼與 Gas 消耗模型、狀態 Trie 的組織原理、以及 Ethash 共識演算法。這些基礎設施共同構成了以太坊區塊鏈的技術地基。
- 以太坊核心協議基礎完整指南:從理論到實作的深度技術分析 — 本文提供以太坊核心協議的完整技術指南,涵蓋共識層、執行層、智慧合約部署、EVM 等核心元件的技術原理與實作細節。援引以太坊白皮書(Buterin, 2014)、黃皮書(Wood, 2014-2023)、Gasper 論文(Buterin et al., 2020)等正式學術文獻強化內容的學術嚴謹性。包含 Gasper 共識機制的數學定義、LMD-GHOST 分叉選擇規則、MPT 狀態管理、EIP-1559 費用燃燒機制、驗證者質押經濟學等完整技術分析。
- 以太坊開發者學習路徑完整指南:從零建構簡化版 EVM、Merkle Patricia Trie 與共識機制實作 — 本文提供一條系統化的以太坊開發者學習路徑,透過實際編寫程式碼來理解以太坊的核心組件。讀者將從頭建構簡化版的以太坊虛擬機(EVM)、實現完整的 Merkle Patricia Trie,並模擬一個基本的工作量證明共識系統。涵蓋 EVM 指令集與執行模型、MPT 的前綴壓縮與哈希驗證、PoW 挖掘與驗證機制、質押證明的驗證者選擇與見證投票等核心主題。提供完整的 Python 程式碼範例與詳細解說,幫助開發者建立對以太坊底層機制的深度理解。
- 以太坊黃皮書完整深度解析系列(二):Gas計算公式推導、EVM執行模型與智能合約部署 — 本文是黃皮書深度解析系列的第二篇,聚焦於 Gas 計算公式的完整推導、EVM 執行模型的形式化描述、以及智能合約部署的狀態轉換過程。我們涵蓋操作碼 Gas 成本的完整推導(棧操作、記憶體操作、存儲操作、調用操作)、EVM 機器狀態的形式化定義、日誌與事件的 Gas 計算、區塊後處理函數、以及 EIP-1559 費用機制的黃皮書更新。這是智慧合約開發者、協議設計者和安全審計師必讀的參考資料。
延伸閱讀與來源
- Ethereum.org Developers 官方開發者入口與技術文件
- EIPs 以太坊改進提案完整列表
- Solidity 文檔 智慧合約程式語言官方規格
- EVM 代碼庫 EVM 實作的核心參考
- Alethio EVM 分析 EVM 行為的正規驗證
這篇文章對您有幫助嗎?
請告訴我們如何改進:
評論
發表評論
注意:由於這是靜態網站,您的評論將儲存在本地瀏覽器中,不會公開顯示。
目前尚無評論,成為第一個發表評論的人吧!