以太坊黃皮書完整深度解析系列(一):形式化定義、狀態轉換函數與區塊結構

本文是黃皮書深度解析系列的第一篇,聚焦於黃皮書的結構框架、核心形式化定義、狀態轉換函數的數學描述、以及區塊結構的嚴謹規範。我們提供中英文對照的術語解釋,涵蓋世界狀態的形式化定義(帳戶模型、nonce 機制)、交易驗證的形式化約束、單筆交易狀態轉換的完整推導、區塊結構的完整定義、以及 EIP-1559 後的費用市場形式化更新。這是深入理解以太坊區塊鏈運作的最佳起點。

以太坊黃皮書完整深度解析系列(一):形式化定義、狀態轉換函數與區塊結構

概述

以太坊黃皮書(Ethereum Yellow Paper)是由 Gavin Wood 博士於 2014 年撰寫的形式化規格文件,定義了以太坊協議的精確數學描述。這份文件是以太坊區塊鏈運作的「終極參考」——任何對以太坊行為的爭議,最終都可以追溯到黃皮書中的定義。截至 2026 年第一季度,黃皮書已經歷多次更新以反映協議演進(如 The Merge、Pectra 升級),但其核心的形式化方法論始終是理解以太坊的最佳起點。

本文是黃皮書深度解析系列的第一篇,將聚焦於黃皮書的結構框架、核心形式化定義、狀態轉換函數的數學描述、以及區塊結構的嚴謹規範。我們將提供中英文對照的術語解釋,幫助讀者同時掌握術語的精確定義和中文表達。

第一部分:黃皮書的結構與定位

1.1 黃皮書的歷史脈絡與版本演進

黃皮書的全名為「Ethereum: A Secure Decentralised Generalised Transaction Ledger」,由以太坊共同創辦人 Gavin Wood 於 2014 年起草。這份文件的誕生源於一個核心需求:為以太坊協議建立無歧義的形式化規格。

在黃皮書問世之前,比特幣的協議規格主要依賴比特幣白皮書和比特幣核心客戶端的實現代碼。這種「代碼即規格」的模式雖然實際可行,但容易導致理解分歧和實現不一致。以太坊從一開始就採用了更嚴謹的方法論:用數學符號精確定義每一個概念,用推導過程展示狀態轉換邏輯。

黃皮書的結構遵循以下層次:

黃皮書結構層次:

┌─────────────────────────────────────────────────────────────────────┐
│  第1層:動機與願景 (Motivation & Vision)                            │
│         - 比特幣的局限性                                             │
│         - 通用智慧合約的需求                                         │
├─────────────────────────────────────────────────────────────────────┤
│  第2層:區塊鏈形式化模型 (Formal Blockchain Model)                  │
│         - 世界狀態 (World State)                                    │
│         - 交易 (Transaction)                                        │
│         - 區塊 (Block)                                              │
├─────────────────────────────────────────────────────────────────────┤
│  第3層:狀態轉換函數 (State Transition Function)                   │
│         - 前狀態 → 交易 → 後狀態                                    │
│         - Gas 消耗計算                                              │
├─────────────────────────────────────────────────────────────────────┤
│  第4層:共識機制 (Consensus Mechanism)                              │
│         - 工作量證明 (PoW)                                          │
│         - 驗證函數                                                   │
├─────────────────────────────────────────────────────────────────────┤
│  第5層:獎勵與激勵模型 (Rewards & Incentives)                      │
│         - 區塊獎勵                                                  │
│         - Uncle 獎勵                                                │
└─────────────────────────────────────────────────────────────────────┘

1.2 形式化符號系統

黃皮書採用了一整套形式化符號系統來描述以太坊。以下是核心符號的定義:

符號英文名稱中文含義數學定義
σWorld State世界狀態σ ∈ B → (A ∪ ∅)
BBlocks區塊集合所有可能區塊的集合
AAccounts帳戶集合所有可能帳戶的集合
μMachine State機器狀態(g, pc, m, i, s)
ΥState Transition狀態轉換函數Υ : (σ, B) → σ'
ΣState Root狀態根區塊頭中的世界狀態哈希

理解這些符號是閱讀黃皮書的基礎。黃皮書的每一個狀態轉換、每一個操作行為,都是用這些符號的組合來描述的。

1.3 黃皮書與其他規格文件的對比

以太坊生態系統中存在多層次的規格文件,它們之間的關係如下:

規格文件層次結構:

┌─────────────────────────────────────────────────────────────────────┐
│  黃皮書 (Yellow Paper)                                             │
│  - 最高權威的形式化定義                                            │
│  - 每個操作的形式化描述                                             │
│  - 數學推導與證明                                                  │
├─────────────────────────────────────────────────────────────────────┤
│  以太坊執行層規格 (Execution Layer Specs)                          │
│  - EVM 操作碼的精確定義                                            │
│  - JSON-RPC 接口規範                                              │
│  - 網路协议規範                                                    │
├─────────────────────────────────────────────────────────────────────┤
│  以太坊共識層規格 (Consensus Layer Specs / Beacon Chain Specs)    │
│  - Casper FFG 共識協議                                             │
│  - 分叉選擇規則                                                    │
│  - 驗證者職責                                                      │
├─────────────────────────────────────────────────────────────────────┤
│  EIPs (Ethereum Improvement Proposals)                              │
│  - 協議升級提案                                                    │
│  - 標準化請求                                                      │
└─────────────────────────────────────────────────────────────────────┘

第二部分:世界狀態的形式化定義

2.1 帳戶狀態的數學模型

黃皮書將每個帳戶定義為一個包含四個組件的元組:

帳戶狀態 (Account State):
    
    σ[a] = (nonce, balance, storage, code)
    
    其中:
    - nonce: 帳戶的交易計數器 (nonce ∈ ℕ₅₆₂)
    - balance: 帳戶餘額 (balance ∈ ℕ₂₅₆)
    - storage: 帳戶的存儲Trie根哈希 (storage ∈ B₃₂)
    - code: 合約程式碼哈希 (code ∈ B₃₂, EOA 為空字節串)

這個定義的關鍵洞察是:帳戶狀態本身不直接存儲存儲內容或程式碼,而是只存儲它們的哈希值。這種設計使得狀態樹的結構更加整潔,同時允許節點選擇性地存儲或刪除歷史狀態。

nonce(隨機數)的形式化定義

nonce 是防止重放攻擊的關鍵機制。黃皮書定義了兩種 nonce:

  1. 交易 nonce (Transaction Nonce):對於所有帳戶,nonce 是嚴格遞增的整數。每次發送交易時,nonce 必須等於帳戶當前的 nonce 值,交易執行後 nonce 增一。
  1. 創建 nonce (Creation Nonce):僅用於合約創建,防止同一發送者在同一 nonce 下創建多個合約。

形式化約束:

∀a ∈ A: valid_transaction(σ, a, t) ⟺
    t.nonce = σ[a].nonce ∧
    σ[a].balance ≥ t.value + t.max_fee ∧
    t.gas_limit ≤ σ[a].balance / G_base

2.2 世界狀態的結構

世界狀態 σ 是從地址到帳戶狀態的映射:

世界狀態 (World State):

    σ : A → (ℕ₂₅₆ × ℕ₂₅₆ × B₃₂ × B_H)
    
    約束條件:
    1. 定義域有限性:只有被修改過的地址才存在於 σ
    2. 完整性:給定任意地址,可以查詢其帳戶狀態或確定其不存在
    3. 一致性:σ 必須與區塊頭中的 stateRoot 一致

世界狀態的組織結構採用 Modified Merkle Patricia Trie (MPTT):

世界狀態Trie結構:

                    狀態根 (State Root)
                           │
            ┌──────────────┼──────────────┐
            │              │              │
        Extension       Branch         Leaf
         Node           Node           Node
            │              │              │
      [共享前綴]      ┌─┬─┬─┬─┐        [地址片段]
                     │ │ │ │ │            │
                    0 1 2 ... f          完整地址哈希
                                              │
                                         帳戶狀態RLP

2.3 存儲樹的形式化定義

每個智慧合約帳戶都有自己獨立的存儲樹,用於存儲合約的持久化狀態:

存儲樹 (Storage Trie):

    σ[a].storageRoot = Tₛ(σ[a].storage)
    
    其中:
    - Tₛ : 存儲鍵值對集合 → MPT 根哈希
    - 鍵:keccak256(keccak256(key || slot) mod 2^256)
    - 值:RLP編碼的256位整數

存儲樹的鍵計算涉及兩層 Keccak-256 哈希:第一層將 (key, slot) 組合成原始鍵,第二層將其哈希以確保均勻分佈和隱私保護。

第三部分:交易的形式化定義

3.1 交易的兩種類型

黃皮書定義了以太坊的兩種核心交易類型:

類型一:消息調用 (Message Call)

交易元組 (Transaction for Message Call):

    t = (nonce, gasPrice, gasLimit, to, value, data, v, r, s)
    
    其中:
    - nonce ∈ ℕ₂₅₆: 發送者的交易計數器
    - gasPrice ∈ ℕ₂₅₆: 單位Gas的價格 (Wei)
    - gasLimit ∈ ℕ₂₅₆: 本交易允許消耗的最大Gas
    - to ∈ A: 目標地址 (若為空,則為合約創建交易)
    - value ∈ ℕ₂₅₆: 轉帳金額 (Wei)
    - data ∈ B: 調用數據 (字節串)
    - v, r, s ∈ ℕ₂₅₆: ECDSA簽名的分量

類型二:合約創建 (Contract Creation)

to = ∅ 時,交易為合約創建交易。黃皮書定義了合約地址的計算方式:

合約地址計算公式:

    addr = BLAKE2b(RLP(sender, nonce))[12:]
    
    具體實現:
    addr = last_20_bytes(keccak256(RLP(n, sender, nonce)))
    
    其中:
    - sender: 創建者的地址
    - nonce: 創建者的當前 nonce(注意:這是合約創建前的nonce)

3.2 交易驗證的形式化約束

每筆交易在執行前必須通過以下形式化驗證:

交易有效性條件 (Transaction Validity):

    VALID(σ, t) ≡ ∧(
        #1  交易簽名有效
            v ∈ {27, 28} ∨ v ∈ {35, 36, 37, 38}  (EIP-155後)
            ecrecover(t) = t.sender
            ∧
        #2  nonce 匹配
            t.nonce = σ[t.sender].nonce
            ∧
        #3  Gas 限制合理
            t.gasLimit ≤ BLOCK_GAS_LIMIT
            t.gasLimit ≥ IntrinsicGas(t)
            ∧
        #4  帳戶餘額充足
            σ[t.sender].balance ≥ t.value + t.max_fee
    )

內稟 Gas (Intrinsic Gas) 是交易執行前必須預留的 Gas,用於支付交易的基礎成本:

內稟Gas計算公式:

    IntrinsicGas(t) = G_transaction + G_txdatazer × z(t.data) + G_txdatanonzero × n(t.data)
    
    其中:
    - G_transaction = 21,000 (基礎成本)
    - G_txdatazer = 4 (每個零字節數據的Gas)
    - G_txdatanonzero = 16 或 68 (每個非零字節數據的Gas,取決於交易類型)
    - z(x) = x 中零字節的數量
    - n(x) = x 中非零字節的數量
    
    EIP-2028 後,calldata 非零字節的成本從 68 降至 16 Gas

3.3 交易的序列化與哈希計算

交易在網路傳輸和簽名時需要進行 RLP 編碼:

交易的RLP編碼格式(不含簽名):

    RLP(t) = RLP_encode([
        t.nonce,
        t.gasPrice,
        t.gasLimit,
        t.to,
        t.value,
        t.data,
        t.chainId,    # EIP-155 後新增
        0,             # EIP-155 後替代 v
        0              # EIP-155 後替代 r
    ])
    
    交易哈希 (Transaction Hash):
    txHash = keccak256(RLP(t))
    
    簽名計算 (Signature):
    msgHash = keccak256(keccak256(RLP(t))[0:hash_length-1] || CHAIN_ID || ∅ || ∅)
    (v, r, s) = ECDSA_sign(msgHash, privateKey)

第四部分:狀態轉換函數的完整推導

4.1 狀態轉換函數的層次結構

黃皮書將狀態轉換定義為多層嵌套函數:

狀態轉換函數層次:

    Υ(σ, T) = Π(σ, T)
    
    其中 Π 是區塊級狀態轉換:
    Π(σ, B) = Ω(B, Υ^L(Υ^G(σ, B.header.ommers), B.transactions))
    
    展開後:
    Π = Ω ∘ (λ B, TXs ↦ Π^B(σ, B, TXs)) ∘ 
        Υ^L ∘ Υ^G
    
    各層含義:
    - Υ^G: 全域狀態預處理 (預期叔塊獎勵調整)
    - Υ^L: 本地區塊狀態轉換 (應用所有交易)
    - Ω: 區塊後處理 (叔塊獎勵、驗證者獎勵)

4.2 本地區塊狀態轉換:Υ^L

Υ^L 將交易序列依次應用於初始狀態:

Υ^L 函數定義:

    Υ^L(σ, B) = σ''
    
    其中:
    σ''' = Υ^L(σ, B) = apply_transactions(σ, B.transactions)
    
    形式化遞迴定義:
    
    Υ^L(σ, TXs) ≡ 
        if TXs = [] then σ
        else Υ^L(Υ(σ, TXs[0]), TXs[1:])
    
    即:
    - 對第一筆交易應用 Υ
    - 將結果作為輸入處理第二筆交易
    - 直到所有交易處理完成

4.3 單筆交易狀態轉換:Υ

單筆交易的狀態轉換 Υ 是黃皮書最核心的形式化定義之一:

交易狀態轉換函數:

    Υ(σ, t) = (σ', g', A)
    
    其中:
    - σ' : 交易執行後的世界狀態
    - g' : 剩餘的 Gas(退還給發送者)
    - A  : 交易所觸發的子執行(子調用列表)
    
    推導過程:
    
    Step 1: 初始檢查
    --------
    ✓ 驗證簽名
    ✓ 檢查 nonce
    ✓ 檢查帳戶餘額
    
    σ'' = σ with σ''[t.sender].nonce += 1
    
    Step 2: 扣減 Gas
    --------
    σ''' = σ'' with σ'''[t.sender].balance -= t.gasLimit × t.gasPrice
    
    Step 3: 計算內稟Gas
    --------
    g_i = IntrinsicGas(t)
    assert g_i ≤ g
    
    Step 4: 創建機器狀態
    --------
    μ₀ = (g - g_i, 0, [], 0, 0)
    
    其中:
    - g: 可用Gas
    - pc: 程序計數器 (初始為0)
    - memory: 記憶體 (空)
    - i: 記憶體擴展字數 (0)
    - s: 棧 (空棧)
    
    Step 5: 執行交易
    --------
    若 t.to = ∅ (合約創建):
        μ' = CREATE(μ, t.sender, t.value, t.data)
    若 t.to ≠ ∅ (消息調用):
        μ' = CALL(μ, t.sender, t.to, t.value, t.data)
    
    Step 6: 計算 Gas 消耗
    --------
    g_used = g - μ'.g
    g_refund = min(g_used × 1/2, g_refund_cap)
    g' = g - g_used + g_refund
    
    Step 7: 最終狀態更新
    --------
    σ''' = apply_MU(σ''', μ')
    σ' = refund_gas(σ''', t.sender, g')

4.4 Gas 退還機制的形式化

黃皮書定義了 Gas 退還公式,用於激勵釋放存儲的操作:

Gas退還公式:

    g_refund = min(g_used × 1/2, σ[origin].refunded_gas)
    
    其中:
    - g_used: 交易實際消耗的Gas
    - 1/2: 退還上限係數
    - σ[origin].refunded_gas: 累積退還Gas
    
    退還觸發條件:
    - SSTORE: 將存儲值從非零改為零 (delete 操作)
    - SELFDESTRUCT: 銷毀合約
    
    退還上限(EIP-3529 修改後):
    g_refund_cap = g_used × 1/5  (2022年上海升級後)

第五部分:區塊結構的完整定義

5.1 區塊頭的形式化定義

區塊頭是區塊的「元數據」,包含連接區塊鏈的所有關鍵信息:

區塊頭結構 (Block Header):

    B_H = (
        parentHash,      # 父區塊的Keccak-256哈希
        ommersHash,      # Uncle區塊列表的哈希
        coinbase,        # 礦工地址 (PoW) / 驗證者公鑰哈希 (PoS)
        stateRoot,       # 區塊執行後的世界狀態根
        transactionsRoot,# 交易列表的Merkle根
        receiptsRoot,    # 交易收據列表的Merkle根
        logsBloom,       # 日誌布隆過濾器
        difficulty,      # 區塊難度值 (PoW)
        number,          # 區塊高度
        gasLimit,        # 區塊Gas上限
        gasUsed,         # 區塊實際使用的Gas
        timestamp,       # 區塊時間戳
        extraData,       # 額外數據 (最多32字節)
        mixHash,         # 混合哈希 (PoW)
        nonce            # 工作量證明隨機數
    )
    
    其中各字段的類型:
    - *_Hash: 32字節哈希值 (B₃₂)
    - *_Root: 32字節哈希值 (B₃₂)
    - coinbase: 20字節地址 (B₂₀)
    - bloom: 256字節布隆過濾器 (B₂₅₆)
    - difficulty/number/gas*: 256位無符號整數 (ℕ₂₅₆)
    - timestamp: 256位時間戳
    - extraData: 可變長度字節串 (最多32字節)

5.2 區塊主體結構

區塊主體結構 (Block Body):

    B_T = (transactions, ommers)
    
    其中:
    - transactions: 交易列表 (按執行順序排列)
    - ommers: Uncle區塊列表 (最多2個)
    
    Uncle區塊的定義:
    Uncle是滿足以下條件的區塊:
    1. 父區塊是當前區塊的祖先區塊(2-7代之內)
    2. 不是當前區塊的祖先區塊
    3. 未被其他區塊標記為Uncle

5.3 狀態根與交易根的計算

區塊頭中的 stateRoot、transactionsRoot、receiptsRoot 是對應 Merkle 樹的根哈希:

Merkle Patricia Trie 根哈希計算:

    狀態根 (State Root):
    stateRoot =MPT_Root(σ)
    其中 σ 是區塊執行完成後的世界狀態
    
    交易根 (Transactions Root):
    transactionsRoot = Trie_Root({ 
        for i in range(len(tx_list)):
            (i, keccak256(RLP(tx_list[i]))) 
    })
    
    收據根 (Receipts Root):
    receiptsRoot = Trie_Root({
        for i in range(len(tx_list)):
            (i, keccak256(RLP(receipt_list[i])))
    })

5.4 交易收據的形式化定義

每筆交易執行後都會生成一個收據,包含執行的結果信息:

交易收據 (Transaction Receipt):

    r = (
        root,           # 狀態根(或失敗標誌)
        cumulativeGas,  # 區塊內累計消耗的Gas
        logsBloom,     # 本交易日誌的布隆過濾器
        logs            # 日誌列表
    )
    
    其中日誌結構:
    log = (address, topics[], data)
    
    日誌的作用:
    1. 記錄合約執行的關鍵事件
    2. 提供事件監聽接口
    3. 用於構建區塊鏈索引

第六部分:區塊難度與工作量證明

6.1 難度調整公式(PoW 時代)

在 The Merge 之前,以太坊使用動態難度調整算法來維持穩定的出塊時間:

難度調整公式:

    BLOCK_diff(n) = 
        parent_diff + 
        parent_diff // 2048 × max(1 - (block_number - parent_number) // 10, -99) +
        2^{floor((block_number - 3000000) // 100000) - 2}
    
    簡化形式:
    D(n) = D(parent) × adjustment_factor + difficulty_boundary
    
    其中:
    - 第一項:難度調整 (根據實際出塊時間)
    - 第二項:難度炸彈 (exponential difficulty increase)

難度炸彈 (Difficulty Bomb) 是以太坊設計的一個「棘輪機制」,用於在預定時間點強制切換到新共識機制。難度炸彈會在 Pre-Merge 的 Edmonton (ETH) 和 Metropolis 升級中被多次延遲,以推遲 The Merge 的實施。

6.2 Ethash 工作量證明

Ethash 演算法的形式化定義:

Ethash 驗證條件:

    verify(HEADER, NONCE) ⟺
        1. nonce < 2^{64}
        2. mixHash = compute_mix(header, nonce)
        3. keccak256(mixHash || keccak256(header' || nonce)) < (2^{256} / DIFFICULTY)
    
    其中:
    - header' 是去除 mixHash 和 nonce 的區塊頭
    - mixHash 是從頭部哈希和 nonce 計算出的混合值

6.3 The Merge 後的共識機制

The Merge 後,區塊結構發生了顯著變化:

合併後區塊結構變化:

PoW 區塊頭字段(移除):
    ❌ mixHash
    ❌ nonce (改為固定值 0x0000000000000000)
    ❌ ommersHash (改為 EMPTY_LIST_HASH)
    ❌ difficulty (改為 0)

PoS 新增字段:
    ✅ beaconBlockRoot: 執行層區塊對應的信標鏈區塊根
    ✅ executionPayloadBranch: 執行層對信標鏈的證明

第七部分:EIP-1559 後的費用市場形式化

7.1 費用市場的形式化改革

EIP-1559 對黃皮書中的費用模型進行了重大更新:

EIP-1559 交易格式:

    t_EIP1559 = (
        chainId,            # 網路標識符
        nonce,              # 交易計數器
        maxPriorityFeePerGas,# 礦工/驗證者小費上限
        maxFeePerGas,      # 願意支付的最大費用
        gasLimit,          # Gas上限
        to,                # 目標地址
        value,             # 轉帳金額
        data,              # 調用數據
        accessList,        # 訪問列表 (可選)
        yParity,           # 替代 v (27/28 → 0/1)
        r, s               # 簽名分量
    )

7.2 Base Fee 調整公式

Base Fee 調整公式:

    BASE_FEE(n) = BASE_FEE(parent) × (1 + Δ)
    
    其中:
    Δ = (gas_used(parent) - gas_target(parent)) / gas_target(parent) × 1/8
    
    約束條件:
    |Δ| ≤ 1/8  (每區塊最大調整幅度為 12.5%)
    
    公式推導:
    當區塊充滿程度 > 50% → Base Fee 上升
    當區塊充滿程度 < 50% → Base Fee 下降
    當區塊充滿程度 = 50% → Base Fee 不變

7.3 費用計算的形式化

交易費用計算:

    total_fee = (base_fee + priority_fee) × gas_used
    
    其中:
    priority_fee = min(maxPriorityFeePerGas, maxFeePerGas - base_fee)
    
    礦工/驗證者收入:
    miner_reward = priority_fee × gas_used + block_reward
    
    Base Fee 燃燒:
    burned = base_fee × gas_used

第八部分:叔塊獎勵機制

8.1 Uncle 區塊的定義與識別

Uncle 區塊識別條件:

    is_uncle(B, U) ⟺
        1. U ≠ B (Uncle 不是主區塊)
        2. ∃ P: P = B.parent ∨ P = P.parent ∨ ... (U 的祖先是 B 的祖先)
        3. depth(U) - depth(B) ≤ 7 (深度差在7代以內)
        4. U 未被其他區塊標記為 Uncle
        5. U 不是 B 的祖先

8.2 Uncle 獎勵公式

Uncle 獎勵計算:

    uncle_reward(uncle, block) = R × (uncle_depth_factor)
    
    其中:
    uncle_depth_factor = (N_R - R_U + 1) / 8
    N_R = 區塊編號
    R_U = Uncle 區塊編號
    
   侄子區塊(包含Uncle的區塊)獎勵:
    nephew_reward = R / 32
    
    其中 R 為基礎獎勵(2 ETH,後因EIP-649調整)
    
    示例:
    若主區塊在高度100,包含高度95的Uncle:
    Uncle 獲得獎勵 = 2 × (100-95+1)/8 = 2 × 6/8 = 1.5 ETH
    主區塊獲得額外獎勵 = 2/32 = 0.0625 ETH

結論:黃皮書閱讀方法論

閱讀黃皮書需要掌握一定的方法論。以下是一些建議:

從宏觀到微觀:首先理解黃皮書的整體結構(第1-3部分提供背景),然後逐步深入具體的形式化定義。

數學符號表:建議先熟練掌握黃皮書使用的數學符號系統。黃皮書附錄提供了完整的符號表。

對照實現:將黃皮書的定義與以太坊客戶端(如 go-ethereum)的實現進行對照,可以加深理解。

追蹤版本變化:黃皮書經歷多次更新,注意區分不同版本的定義差異。GitHub 上的黃皮書倉庫記錄了所有變更歷史。

參考資源

延伸閱讀與來源

這篇文章對您有幫助嗎?

評論

發表評論

注意:由於這是靜態網站,您的評論將儲存在本地瀏覽器中,不會公開顯示。

目前尚無評論,成為第一個發表評論的人吧!