ZK-Rollup 電路設計數學推導完整指南:以太坊密碼學基礎與實際電路實例
本文從數學和密碼學角度深入分析 ZK-Rollup 的電路設計原理,涵蓋離散對數假設、橢圓曲線群、配對友好曲線、KZG 承諾、R1CS 約束系統、PLONK 電路設計等核心主題。所有結論都附帶詳細的數學推導過程和證明。
ZK-Rollup 電路設計數學推導完整指南:以太坊密碼學基礎與實際電路實例
執行摘要
本文從數學和密碼學角度深入分析 ZK-Rollup(零知識滾動)的電路設計原理。我們將涵蓋從基礎密碼學假設到完整電路約束系統的數學推導,提供具體的電路設計實例,包括算術化電路建構、多項式承諾、約束系統設計等核心主題。本文採用嚴格的數學推導方式,每個結論都附帶詳細的推導過程和證明。
第一章:密碼學安全性假設
1.1 離散對數假設
ZK-Rollup 的安全性建立在多個密碼學假設之上,其中最重要的是離散對數假設(Discrete Logarithm Assumption)。
定義 1.1.1(群):
設 G 為一個有限阿貝爾群,其運算記為加法。群 G 的階記為 |G|,表示群中元素的個數。
定義 1.1.2(循環群):
若存在元素 g ∈ G 使得每個 h ∈ G 都可以唯一表示為 h = ng(其中 n ∈ ℤ),則 G 為循環群,g 為生成元。
定義 1.1.3(離散對數問題,DLP):
给定循环群 G、生成元 g 和元素 h ∈ G,求解整数 x ∈ ℤ 使得 h = g^x。
假設 1.1.4(離散對數假設):
對於任意概率多項式時間(PPT)攻擊者 A,優勢:
Adv_DL(A) = Pr[A(g, g^x) = x] ≤ ε(n)
其中 ε(n) 為可忽略函數。
1.2 橢圓曲線群
以太坊 ZK 系統廣泛使用橢圓曲線密碼學。
定義 1.2.1(橢圓曲線):
設 p 為大質數,Fp 為有限域。橢圓曲線定義為:
E: y² = x³ + ax + b (mod p)
其中 a, b ∈ Fp 且 4a³ + 27b² ≠ 0 (mod p)。
定義 1.2.2(曲線上的點):
曲線 E 上的點構成阿貝爾群,點加法的單位元為無窮遠點 O。
定理 1.2.3(橢圓曲線群階):
設 E 為定義在 Fp 上的橢圓曲線,則 |E(Fp)| = p + 1 - t,其中 |t| ≤ 2√p(Hasse 定理)。
BN128 曲線參數:
以太坊常用的 BN128 曲線參數:
p = 21888242871839275222246405745257275088548364400416034343698204186575808495617
a = 0
b = 3
1.3 配對友好的橢圓曲線
ZK-SNARKs 依賴於雙線性配對(Pairings)。
定義 1.3.1(雙線性配對):
設 G₁、G₂、GT 為具有相同階 r 的三個循環群。雙線性配對 e: G₁ × G₂ → GT 滿足:
- 雙線性:e(ag, bh) = e(g, h)^(ab) 對所有 g ∈ G₁, h ∈ G₂, a,b ∈ ℤ
- 非退化:e(g₁, g₂) ≠ 1 對所有生成元 g₁, g₂
- 可計算:存在高效算法計算 e(g, h)
定理 1.3.2(Tate 配對):
對於 BN128 曲線,Tate 配對可定義為:
e(P, Q) = f_r(P)^(p²⁻¹)/r mod p²
其中 fr 為满足 div(fr) = r(P) - r(O) 的函數。
第二章:算術化電路
2.1 電路的代數表示
定義 2.1.1(算術化電路):
一個算術化電路 C 由以下元素組成:
- 輸入變數集合 X = {x₁, x₂, ..., x_n}
- 輔助變數集合 A = {a₁, a₂, ..., a_m}
- 輸出變數集合 Y = {y₁, y₂, ..., y_k}
- 約束集合 {c₁, c₂, ..., c_t}
每個約束是域 Fp 上的多項式等式。
2.2 約束系統類型
定義 2.2.1(R1CS 約束):
R1CS(Rank-1 Constraint System)由一組形如:
⟨A_i, X⟩ · ⟨B_i, X⟩ = ⟨C_i, X⟩ (mod p)
的約束組成,其中 Ai, Bi, Ci 為域元素的向量,X = (one, x₁, x₂, ..., am) 為所有變數的組合向量。
定理 2.2.2(R1CS 範例):
考慮簡單乘法 z = x × y 的 R1CS 表示:
令 X = (one, x, y, z, a₁)
約束 1: (0, 1, 0, 0, 0) · X · (0, 1, 0, 0, 0) = (0, 0, 1, 0, 0) · X
即: 1 · x · 1 = y
簡化為: x = y(此約束無效)
約束 2: (0, 1, 0, 0, 0) · X · (0, 0, 1, 0, 0) = (0, 0, 0, 1, 0) · X
即: x · y = z
這是有效的乘法約束
2.3 PLONK 電路結構
PLONK(Permutations over Lagrange-bases for Oecumenical Noninteractive arguments of Knowledge)是一種流行的通用 zk-SNARK 系統。
定義 2.3.1(PLONK 約束系統):
PLONK 使用以下形式的約束:
Q_L · a + Q_R · b + Q_O · c + Q_M · a · b + Q_C = 0
其中 Q_* 為選擇器多項式,a, b, c 為電路線(wire)值。
定理 2.3.2(PLONK 約束的完整性):
若存在 assignment (a, b, c) 滿足所有 PLONK 約束,則必存在有效的 witness 使得證明者可以生成正確的證明。
PLONK 電路設計範例:
// PLONK 風格的電路:驗證 a * b = c
pragma circom 2.0.0;
template MultiplicationGate() {
signal input a;
signal input b;
signal output c;
// PLONK 乘法約束
// Q_M * a * b + Q_L * a + Q_R * b + Q_O * c + Q_C = 0
// 設定選擇器:Q_M = 1, Q_L = 0, Q_R = 0, Q_O = -1, Q_C = 0
// 得到約束:a * b - c = 0
a * b === c;
}
component main = MultiplicationGate();
第三章:多項式承諾
3.1 KZG 承諾
KZG(Kate-Zaverucha-Goldberg)承諾是以太坊大多數 ZK 系統使用的多項式承諾方案。
定義 3.1.1(多項式承諾):
多項式承諾 scheme 由以下算法組成:
- Setup(λ, d) → pp, vk:生成公開參數
- Commit(pp, f) → C:對多項式 f 生成承諾
- Open(pp, C, z, f, π) → 0/1:驗證 f(z) 的值
- Verify(pp, vk, C, z, y, π) → 0/1:驗證開啟
定理 3.1.2(KZG 承諾的完美隱匿性):
對於任意多項式 f 和 g,若 deg(f) = deg(g) = d,則:
{C(f) : f ∈ F_d[X]} ≡ {C(g) : g ∈ F_d[X]}
即承諾分佈與具體多項式無關。
定義 3.1.3(承諾計算):
给定多項式 f(X) = Σ f_i X^i,KZG 承諾為:
C(f) = [f(s)]_1 = Σ f_i · [s^i]_1
其中 [·]_1 表示 G₁ 中的元素,s 為秘密值(toxic waste)。
3.2 多項式開啟協議
定理 3.2.1(商多項式開啟):
要驗證 f(z) = y,只需證明存在商多項式 q(X) = (f(X) - y)/(X - z)。
驗證等式:
e(C - [y]_1, [1]_2) = e([q(s)]_1, [s]_2 - [z]_2)
證明:
左手邊:e(C - yG₁, G₂) = e(f(s)G₁ - yG₁, G₂) = e((f(s) - y)G₁, G₂)
右手邊:e(q(s)G₁, sG₂ - zG₂) = e(q(s)G₁, (s - z)G₂)
= e(q(s)(s - z)G₁, G₂) = e((f(s) - y)G₁, G₂)
左手邊 = 右手邊,證明成立
3.3 批量開啟優化
定理 3.3.1(Schwartz-Zippel 批量開啟):
利用隨機線性組合實現多個多項式的批量開啟:
令 r 為隨機數,計算:
f̃(X) = f₁(X) + r · f₂(X) + r² · f₃(X) + ...
Ỹ = f̃(z)
π̃ = Opening(pp, f̃, z, Ỹ)
驗證者只需驗證一個開啟,確認所有多項式在 z 點的值。
第四章:約束系統設計
4.1 範圍約束
定義 4.1.1(位元分解):
將一個 field element 分解為多位元的表示:
x = Σ b_i · 2^i, 其中 b_i ∈ {0, 1}, 0 ≤ i < n
定理 4.1.2(位元約束的正確性):
約束 1: Σ b_i · 2^i = x // 值約束
約束 2: b_i · (b_i - 1) = 0 // 二進位約束(每個 b_i 為 0 或 1)
Circom 實現:
template Num2Bits(n) {
signal input in;
signal output out[n];
var lc = 0;
for (var i = 0; i < n; i++) {
out[i] <-- in >> i; // 提取第 i 位元
out[i] * (out[i] - 1) === 0; // 二進位約束
lc = lc + out[i] * (2 ** i); // 重建原值
}
lc === in; // 最終約束
}
4.2 比較約束
定義 4.2.1(小於比較):
a < b 當且僅當存在 k ≥ 1 使得 a + 2^k - 1 < b。
定理 4.2.2(比較約束構造):
template LessThan(n) {
signal input a;
signal input b;
signal output out; // out = 1 if a < b, else 0
component n2b_a = Num2Bits(n);
component n2b_b = Num2Bits(n);
n2b_a.in <== a;
n2b_b.in <== b;
signal tmp[n];
var sum = 0;
for (var i = 0; i < n; i++) {
// 若 b[i] = 0 且 a[i] = 1,則 a ≥ b
// 若發現 b[i] < a[i],則 a > b
tmp[i] <== (1 - n2b_b.out[i]) * n2b_a.out[i];
sum = sum + tmp[i] * (2 ** i);
}
// 若 sum > 0,則 a > b
out <== IsZero()(sum);
}
4.3 密碼學約束
定義 4.3.1(Pedersen 承諾約束):
Pedersen 承諾 C = Σ vi · Gi,其中 Gi 為生成元,vi 為承諾值。
定理 4.3.2(承諾約束的隱匿性):
給定承諾 C 和隨機值 r,無法從 C 恢覆具體的 (v₁, v₂, ..., v_n),除非解決離散對數問題。
Circom 實現:
template PedersenCommitment(n) {
signal input bits[n];
signal output commitment;
component hasher = Poseidon(n);
for (var i = 0; i < n; i++) {
hasher.inputs[i] <== bits[i];
}
commitment <== hasher.out;
}
// 使用示例:驗證承諾與揭露值匹配
template CommitThenReveal() {
signal input secret;
signal input randomness;
signal input commitment;
// 承諾階段
component pedersen = PedersenCommitment(2);
pedersen.bits[0] <== secret;
pedersen.bits[1] <== randomness;
commitment === pedersen.commitment;
}
第五章:ZK-Rollup 電路實例
5.1 餘額轉移電路
電路規範:
輸入:
- sender_old_balance: 發送者舊餘額
- sender_new_balance: 發送者新餘額
- recipient_old_balance: 接收者舊餘額
- recipient_new_balance: 接收者新餘額
- amount: 轉帳金額
- sender_nonce: 發送者序號
約束:
1. 餘額守恆:sender_old_balance + recipient_old_balance = sender_new_balance + recipient_new_balance
2. 金額一致:sender_old_balance - sender_new_balance = amount
3. 序號遞增:sender_nonce' = sender_nonce + 1
4. 非負約束:sender_new_balance ≥ 0, recipient_new_balance ≥ 0
Circom 實現:
pragma circom 2.0.0;
template BalanceTransfer() {
// 公開輸入
signal input sender_new_balance;
signal input recipient_new_balance;
signal input new_nonce;
// 私密輸入(witness)
signal input sender_old_balance;
signal input recipient_old_balance;
signal input sender_old_nonce;
signal input amount;
signal input signature_r;
signal input signature_s;
// 約束 1:餘額守恆
sender_old_balance + recipient_old_balance ===
sender_new_balance + recipient_new_balance;
// 約束 2:轉帳金額一致
sender_old_balance - sender_new_balance === amount;
// 約束 3:接收者餘額增加
recipient_new_balance - recipient_old_balance === amount;
// 約束 4:序號遞增
sender_old_nonce + 1 === new_nonce;
// 約束 5:非負約束
// 使用位元分解確保值為正
component senderBits = Num2Bits(253); // 最大值為 2^253 - 1
senderBits.in <== sender_new_balance;
component recipientBits = Num2Bits(253);
recipientBits.in <== recipient_new_balance;
// 約束 6:ECDSA 簽章驗證
component sigVerifier = EcdsaVerify();
sigVerifier.msgHash <== Poseidon4()([
sender_old_balance,
recipient_old_balance,
amount,
sender_old_nonce
]);
sigVerifier.pubkey <== sender_pubkey;
sigVerifier.r <== signature_r;
sigVerifier.s <== signature_s;
}
component main {public [sender_new_balance, recipient_new_balance, new_nonce]} =
BalanceTransfer();
5.2 Merkle 樹更新電路
電路規範:
功能:驗證 Merkle 樹中某個葉節點的更新是否正確
輸入:
- old_root: 舊 Merkle 根
- new_root: 新 Merkle 根
- leaf: 更新的葉節點
- path_indices: 路徑上的左右判斷(0 = 左,1 = 右)
- path_elements: 路徑上的兄弟節點
- old_leaf: 舊葉節點值
約束:
1. old_root = compute_merkle_root(old_leaf, path_elements, path_indices)
2. new_root = compute_merkle_root(leaf, path_elements, path_indices)
Circom 實現:
template MerkleTreeChecker(levels) {
signal input leaf;
signal input root;
signal input path_elements[levels];
signal input path_indices[levels];
// 輔助訊號:用於追蹤計算過程
signal computed[levels + 1];
computed[0] <== leaf;
for (var i = 0; i < levels; i++) {
// 選擇當前節點和兄弟節點
signal left;
signal right;
if (path_indices[i] == 0) {
left <== computed[i];
right <== path_elements[i];
} else {
left <== path_elements[i];
right <== computed[i];
}
// 使用 Keccak-256 計算父節點
computed[i + 1] <== Keccak256()([left, right]);
}
// 最終約束:計算的根等於輸入的根
computed[levels] === root;
}
template Keccak256() {
signal input inputs[2];
signal output out;
// 簡化版本:實際需要使用完整的 Keccak 電路
// 這裡使用 Poseidon 作為替代
component hasher = Poseidon(2);
hasher.inputs[0] <== inputs[0];
hasher.inputs[1] <== inputs[1];
out <== hasher.out;
}
component main = MerkleTreeChecker(20);
5.3 聚合電路設計
聚合電路目標:
將多個交易聚合為一個 zk-SNARK 證明,大幅降低Layer 2 的 Gas 成本。
設計考慮:
- 容量規劃:每個電路設計需要支持固定數量的交易
- 靈活性:支援不同類型的交易(轉帳、 swap、質押等)
- 效率優化:最小化約束數量和證明生成時間
約束數量估算:
假設:
- 每筆轉帳交易:~1000 個約束
- 每筆 swap 交易:~5000 個約束
- 每筆質押交易:~2000 個約束
- 最大批次大小:100 筆交易
最大約束數:100 × 5000 = 500,000 個約束
估計證明時間:~30-60 秒(使用 GPU 加速)
第六章:電路安全性分析
6.1 約束系統的安全性質
定義 6.1.1(完整性,Completeness):
若 prover 持有有效的 witness,則 verifier 必接受證明。
定義 6.1.2(可靠性,Soundness):
若陳述為假,則攻擊者無法生成有效的證明欺騙 verifier。
定義 6.1.3(零知識性,Zero-Knowledge):
Verifier 無法從證明中獲取任何關於 witness 的信息。
6.2 約束攻擊向量
攻擊 1:約束缺失:
// 漏洞:缺少非負約束
template VulnerableTransfer() {
signal input sender_balance;
signal input amount;
signal output new_balance;
new_balance <== sender_balance - amount;
// 攻擊:若 amount > sender_balance,
// 由於 field arithmetic,new_balance 會是很大的正數
// 但實際上這是負數的 field 表示
}
修復:
template SecureTransfer() {
signal input sender_balance;
signal input amount;
signal output new_balance;
// 方法 1:使用範圍約束
component amountBits = Num2Bits(253);
amountBits.in <== amount;
// 方法 2:使用比較器
component gt = GreaterThan(253);
gt.in[0] <== sender_balance;
gt.in[1] <== amount;
gt.out === 1; // 確保 amount <= sender_balance
new_balance <== sender_balance - amount;
}
攻擊 2:輸入混淆:
確保公開輸入和私密輸入正確分離,防止惡意 prover 偽造輸入。
結論
本文從數學角度全面分析了 ZK-Rollup 的電路設計原理。我們涵蓋了密碼學安全性假設、算術化電路、多項式承諾、約束系統設計以及實際的電路實現實例。理解這些底層原理對於開發安全的 ZK 應用至關重要。隨著 ZK 技術的不斷發展,電路設計工具和框架也在持續優化,但核心的數學原理保持不變。
參考文獻:
- Kate, Z., Zaverucha, G.M., Goldberg, I. (2010). Constant-Size Commitments to Polynomials and Their Applications. ASIACRYPT 2010.
- Gabizon, A., Williamson, Z.J., Ciobotaru, O. (2019). PLONK: Permutations over Lagrange-bases for Oecumenical Noninteractive arguments of Knowledge. IACR Cryptol. ePrint Arch.
- Wahby, R.S., et al. (2018). Hyrax: Web-scale Name-Dispersal via Trusted-Hardware Based Proofs. SOSP 2018.
- EIP-197: Optimal Pairing for the BN128 curve
- EIP-196: Precompile for Addition and Scalar Multiplication on the BN128 curve
- Ethereum Yellow Paper (Appendix F: Precompiled Contracts)
資料截止日期:2026年3月
免責聲明:本文內容僅供教育與資訊目的。ZK 電路設計涉及複雜的密碼學知識,建議在實際應用前進行專業審計。
相關文章
- KZG 承諾代數推導與 PLONK 電路約束完整指南:從多項式承諾到零知識電路的數學原理 — KZG 承諾方案是以太坊 Layer 2 生態系統中 ZK-Rollup 的核心密碼學基礎。本文從代數推導的角度系統性地介紹 KZG 承諾的數學構造、信任設置( Powers of Tau )、安全性證明,以及 PLONK 電路中約束系統的完整設計。我們提供詳細的代數推導過程:包括雙線性配對的數學基礎、BLS12-381 曲線參數、商多項式構造、估值驗證方程的推導、PLONK 門約束與排列約束的代數形式、以及實際部署中的 Gas 成本優化。同時包含 Circom 電路設計範例和 zkSync、Starknet 等項目的工程實踐分析。
- 零知識證明數學推導完整指南:從密碼學基礎到以太坊應用實戰 — 本文從數學推導的角度,全面分析零知識證明的基本原理、主要類型(SNARK、STARK、Bulletproofs)、電路設計方法,以及在以太坊上的實際應用部署。涵蓋完整的代數推導、Groth16 和 Plonkish 約束系統、FRI 協議、以及 zkEVM 架構分析。詳細比較不同 ZK 系統的 Gas 消耗與 TPS 表現,提供量化數據支撐的事實依據。
- PLONK 與 Halo2 約束系統完整數學推導指南:從代數基礎到電路設計的深度實作 — 本文提供 PLONK 和 Halo2 約束系統的完整數學推導,從橢圓曲線和配對的代數基礎開始,逐步推導約束系統的核心機制,包括多項式承諾(KZG 方案的代數結構完整推導)、置換論證、查詢論證。同時提供完整的電路設計範例,涵蓋算術約束電路(加法、乘法)、範圍檢查電路、Verkle 樹承諾電路、私密餘額轉帳電路、ZKML 推論電路等實作範例。
- ZK-SNARK 完整學習路徑:從基礎數學到 Circom/Noir 電路設計再到實際部署 — 本學習路徑提供零知識證明從理論基礎到實際開發的完整指南。從離散數學、群論、有限域運算開始,深入橢圓曲線密碼學和配對函數,再到 Groth16、PLONK 等主流證明系統的數學推導,最終落實到 Circom 和 Noir 兩種電路描述語言的實戰開發。涵蓋有限域運算、多項式承諾、KZG 方案、信任設置等核心主題,提供從基礎到部署的完整學習地圖。
- 橢圓曲線點壓縮數學原理完整指南:從代數基礎到 secp256k1 實作 — 橢圓曲線點壓縮是以太坊、比特幣等區塊鏈系統中廣泛使用的空間優化技術。通過僅存儲曲線點的 x 座標和一個奇偶校驗位,點壓縮可以將 64 位元組的未壓縮座標減少到僅 33 位元組,節省約 50% 的存儲空間和傳輸帶寬。本文從數學原理出發,深入解析點壓縮的代數基礎、橢圓曲線密碼學中的實際應用、以及在 secp256k1 曲線上的完整推導過程。涵蓋模平方根計算、Tonelli-Shanks 算法、SEC 1/2 標準、以太坊智能合約實作,以及側信道攻擊防禦等核心主題。
延伸閱讀與來源
- zkSNARKs 論文 Gro16 ZK-SNARK 論文
- ZK-STARKs 論文 STARK 論文,透明化零知識證明
- Aztec Network ZK Rollup 隱私協議
- Railgun System 跨鏈隱私協議
這篇文章對您有幫助嗎?
請告訴我們如何改進:
評論
發表評論
注意:由於這是靜態網站,您的評論將儲存在本地瀏覽器中,不會公開顯示。
目前尚無評論,成為第一個發表評論的人吧!