ZK-SNARK 數學推導完整指南:從零知識證明到 Groth16、PLONK、STARK 系統的深度數學分析
本文從數學基礎出發,完整推導 Groth16、PLONK 與 STARK 三大主流 ZK 系統的底層原理,涵蓋橢圓曲線密碼學、配對函數、多項式承諾、LPC 證明系統等核心技術,同時提供 Circom 與 Noir 電路開發的實戰程式碼範例。截至 2026 年第一季度,ZK-SNARK 已被廣泛部署於 zkRollup、隱私協議、身份驗證系統等場景。
ZK-SNARK 數學推導完整指南:從零開始搞懂簡潔非互動式零知識知識證明
說實話,ZK-SNARK 這個主題,我在網上看到的文章大部分都是兩極分化:一種是「太學術了看不懂」,另一種是「太簡化了說了等於沒說」。我自己當初學這個的時候,也是被折騰了好一段時間。
所以這篇文章的目標很明確:用「夠數學但不至於催眠」的方式,帶你從零推導 ZK-SNARK 的核心原理。我會盡量解釋每一個步驟背後的「直覺」,因為數學推導如果沒有直覺支撐,很快就會變成天書。
為什麼需要 ZK-SNARK?
在直接進入數學之前,讓我們先搞清楚「為什麼要有這東西」。
傳統的區塊鏈驗證是這樣的:你說你做了一筆交易,好,我重新執行一遍這筆交易,確認結果對不對。比特幣就是這麼做的——每個節點都是一台「小電腦」,收到交易後默默執行一遍腳本。
問題來了:如果交易超級複雜呢?比如 zkRollup 要證明「我在鏈下執行了 1000 筆 DeFi 交易,然後得到了這個最終狀態」。你讓主鏈的每個節點重新執行 1000 筆交易?光是 Gas 就能讓你破產。
ZK-SNARK 的核心思想是:不要重新計算,給我一個「證明」就行。
更精確地說,ZK-SNARK 讓 Prover(證明者)可以說:「我知道一個秘密 x,使得 F(x) = y 成立。我不會告訴你 x 是什麼,但我可以給你一個證明 π。如果你相信這個證明,你就可以確信確實存在這樣一個 x。」
這裡有幾個關鍵詞:
- 簡潔(Succinct):證明長度很短,驗證速度很快
- 非互動(Non-interactive):不需要來回對話,Prover 發一次,Verifier 驗一次就結束
- 零知識(Zero-Knowledge):Verifier 除了「證明為真」這件事之外,什麼額外資訊都得不到
- 知識(Knowledge):Prover 必須真的「知道」那個秘密,否則造不出有效的證明
這個「知識」听起来有點玄,但數學上是可以嚴格定義的——後面我們會看到具體怎麼定義。
第一步:把問題轉換成代數電路
所有的 ZK-SNARK 系統,第一步都是把你要證明的計算問題轉換成「代數電路」。
什麼是代數電路?想象一堆「門」(gate),每個門做最基本的運算——加法或乘法。電線(wire)把這些門連接起來,承載著數值。
電路的輸入是公開的 x 和私密的 witness w。輸出應該是 0(表示「計算正確」)。
形式上,我們把電路表示成一系列約束:
a₁ + a₂ = a₃
a₃ × a₄ = a₅
...
每條電線上有一個值。這些約束必須全部滿足,電路才算正確執行。
舉個具體例子。假設我們想證明:「我知道一個數 a,使得 a³ + a + 5 = 35」。這很簡單,a=3 就是答案。
我們可以把這個計算轉換成電路:
Input₁ = a (private)
Input₂ = a
Input₃ = a
Wire₁ = Input₁ × Input₂ // a²
Wire₂ = Wire₁ × Input₃ // a³
Wire₃ = Wire₂ + Input₁ // a³ + a
Wire₄ = Wire₃ + 5 // a³ + a + 5
Output = Wire₄ - 35 = 0 // 這個約束必須滿足
這就是電路的直覺:把複雜計算拆解成簡單的加法和乘法操作。
第二步:從電路到 R1CS
R1CS(Rank-1 Constraint System,一階約束系統)是一種標準化的電路描述格式。
每個約束的格式是:
(A · z) × (B · z) - (C · z) = 0
其中:
- z 是一個向量,包含所有電線的值(包括公開輸入、私密 witness、中間結果)
- A、B、C 是矩陣(或者更常見地說,是矩陣的某一列)
- 「·」是向量內積
這個格式看起來很抽象,但它有一個很好的性質:任何可以用加法和乘法表示的計算,都可以轉換成 R1CS。
拿剛才的例子來說:
約束 1: Input₁ = a
約束 2: Input₂ = a
約束 3: Input₃ = a
約束 4: Wire₁ - Input₁ × Input₂ = 0
約束 5: Wire₂ - Wire₁ × Input₃ = 0
約束 6: Wire₃ - Wire₂ - Input₁ = 0
約束 7: Wire₄ - Wire₃ - 5 = 0
約束 8: Output - Wire₄ + 35 = 0
每個約束都可以轉換成 R1CS 格式。具體來說,對於 c = a × b,約束是:
左邊: 1 × c = 1
右邊: a × b
約束: 1 × c - a × b = 0
寫成向量形式,對於某些 wire 的係數是 1,某些是 -1,幾乎所有其他係數都是 0。
第三步:從 R1CS 到 QAP
R1CS 的問題是:如果你有 n 個約束,你就需要驗證 n 次。當 n 很大(比如電路有幾百萬個門)的時候,這還是很慢。
QAP(Quadratic Arithmetic Program,二次算數程序) 把這 n 個約束「打包」成幾個多項式。
核心思想是:如果一個多項式在 n 個不同點上都等於 0,那這個多項式一定是 (x-1)(x-2)...(x-n) 的倍數。
這是一個經典的多項式定理:如果兩個多項式在 d+1 個點上相等,那它們就是同一個多項式。
應用到 R1CS,我們把約束 j 的 A、B、C 係數變成多項式 Aⱼ(x)、Bⱼ(x)、Cⱼ(x),使得:
- 對約束 j,這些多項式在 x=j 時的值,正好等於約束 j 的係數
然後,定義:
A(x) = Σⱼ Aⱼ(x) · zⱼ
B(x) = Σⱼ Bⱼ(x) · zⱼ
C(x) = Σⱼ Cⱼ(x) · zⱼ
其中 zⱼ 是約束 j 中各 wire 的值。
數學上可以證明:所有約束都滿足,當且僅當 (A·B - C)(j) = 0 對所有 j=1,2,...,n 成立。
根據上面的多項式定理,這意味著存在一個多項式 H(x),使得:
A(x) · B(x) - C(x) = H(x) · Z(x)
其中 Z(x) = (x-1)(x-2)...(x-n)。
所以驗證「電路正確執行」這件事,現在變成了:「存在一個多項式 H,使得上述等式成立」。這個性質讓我們可以把「多次檢查」變成「一次多項式檢查」。
第四步:多項式承諾
現在的問題是:Prover 怎麼讓 Verifier 相信「確實存在這樣一個 H」?
直接把 A(x)、B(x)、C(x)、H(x) 全部發給 Verifier?不行,因為這些多項式可能很大,而且如果暴露了完整多項式,Verifier 可能就能推斷出 witness。
這裡我們需要「多項式承諾」(Polynomial Commitment)。
最常用的多項式承諾方案是 KZG(Kate-Zaverucha-Goldberg)承諾。
KZG 承諾的核心思想很巧妙:
- 首先,有一個「信任設置」(Trusted Setup)。假設存在一個神秘的秘密值 τ(tau),但這個 τ 在設置完成後就被「毀滅」了——沒有人知道 τ 是多少。
- Prover 對多項式 f(x) 的承諾是:
Commit(f) = f(τ) · G
其中 G 是一個生成元(generator point)。這看起來像是「在秘密點 τ 上評估多項式」,只不過是通過橢圓曲線來實現的。
- 驗證的時候,Prover 需要「開啟」(open)承諾,證明「這個承諾確實是對多項式 f 的承諾」。這通過提供一個「多項式除法」的證明來實現。
數學上可以證明:如果 Prover 真的知道 f 和 g,使得 f = q·g + r(其中 r 的次數小於 g),那麼:
Commit(f) = q(τ)·G + r(τ)·G
所以要開啟,只需要提供 q(τ)·G 的值。
KZG 承諾的優點是:
- 承諾長度是一個橢圓曲線點,很短
- 驗證只需要幾次配對(pairing)運算,很快
- 承諾是「同態的」——你可以把承諾加起來,然後一次性開啟
缺點是:
- 需要信任設置。如果 τ 洩漏了,Prover 可以構造假證明
- 信任設置是「電路相關的」——每個電路都需要自己的設置
第五步:Groth16 的具體構造
Groth16 是最流行也是最早實用的 ZK-SNARK 方案之一。它把上面的理論框架轉換成了一個可以實際運作的協議。
Groth16 的設置分為兩個階段:
階段一(通用): 生成 CRS(Common Reference String,公共參考字串)。CRS 包括:
[G₁¹, G₁ᵃ, ..., G₁ᵃᵈ] 和 [G₂¹, G₂ᵇ, ..., G₂ᵇᵈ]
其中 G₁、G₂ 是不同群(通常是橢圓曲線的兩個子群),a 和 b 是隨機選擇的秘密值。
階段二(電路特定): 使用 CRS 和電路參數,生成電路特定的 proving key 和 verification key。
Prover 的工作:
- 根據 witness 計算 A、B、C 多項式
- 計算 H = (A·B - C) / Z
- 使用 CRS 加密計算 πA = A(α)·G₁, πB = B(β)·G₂, πC = C(γ)·G₁
- 輸出證明 (πA, πB, πC)
Verifier 的工作:
- 使用 verification key 和公開輸入,計算 C 的「部分承諾」
- 驗證配對等式:
e(πA, πB) = e(C̃, G₂) · e(H̃, Z̃)
其中 H̃ 和 Z̃ 是從 verification key 和公開輸入構造的。
如果等式成立,Verifier 就可以確信:Prover 知道一個 witness,使得電路正確執行。
為什麼這是「零知識」的?
到目前為止,我們描述的協議只證明了「電路正確執行」,但沒有確保「witness 沒有洩漏」。
要實現零知識,Prover 需要對 witness 做「零知識遮罩」:
A := A₀ + Σ wᵢ·Aᵢ (witness 線性組合)
改為
A := A₀ + Σ wᵢ·Aᵢ + δ·A_random
其中 δ 是一個隨機數。
類似地,B 和 C 也要加上隨機遮罩。
這些隨機遮罩確保:即使 Prover 知道一個有效的 witness,她也可以通過添加隨機偏移來「偽造」另一個看起來完全不同的 witness。這使得 Verifier 無法從證明中推斷出具體的 witness 值。
數學上可以嚴格證明:存在一個模擬器,在不知道 witness 的情況下,也能生成與真實證明「不可區分」的模擬證明。這正是「零知識」的定義。
PLONK:通用信任設置的突破
Groth16 的一個主要缺點是:每個電路都需要一個新的信任設置(階段二)。這在實際應用中很不方便——如果你的電路升級了,你就得重新做一次「儀式」(ceremony)。
PLONK(Permutations over Lagrange-bases for Oecumenical Noninteractive arguments of Knowledge) 解決了這個問題。
PLONK 的核心創新是:
- 通用可信設置:階段二的 CRS 與電路無關。你只需要做一次「powers of tau」儀式,就可以用於任何 PLONK 電路。
- 自定義約束:PLONK 允許你定義「自定義門」(custom gate),而不只是標準的加法和乘法。這讓某些特定計算更高效。
- 置換論證:PLONK 引入了一種聰明的技術來處理「相同值」約束(比如「這兩條 wire 必須相等」)。這簡化了電路描述,提高了效率。
PLONK 的信任設置分為兩個階段:
- powers of tau:生成一個「通用 CRS」,大小與最大電路規模成正比
- 電路特定階段:根據具體電路,從通用 CRS 生成 proving key 和 verification key
這個兩階段結構讓 PLONK 更實用:你可以在主網上進行一次大規模的 powers of tau 儀式,然後任何人都可以用這個 CRS 來生成自己的電路 proving key。
Halo2:無需信任設置的替代方案
如果「信任設置」讓你頭疼,Halo2 提供了另一種選擇。
Halo2 使用的是「累積型」(recursive)證明系統,不需要傳統的「 trusted setup」。它的核心思想是:
- 你可以把一個證明「壓縮」成一個更小的「壓縮證明」
- 這個壓縮過程本身也產生一個證明
- 重複這個過程,直到得到一個「幾乎是零大小」的最終證明
Halo2 的技術基礎是「內積論證」(Inner Product Argument)。它允許你對一個向量做承諾,然後高效地證明「這個向量的某個子集之和等於某個值」之類的聲明。
Halo2 的優點:
- 完全不需要信任設置
- 電路升級不需要重新做設置
- 適合「長期運行的」應用場景
缺點是證明尺寸比 KZG-based 方案稍大。
Zcash 在其最新的升級中採用了 Halo2,這是它「不需要信任設置」承諾的技術基礎。
STARK vs SNARK:不需要信任設置的另一條路
STARK(Succinct Transparent Arguments of Knowledge)代表了一條完全不同的技術路線。
與 SNARK 的主要區別:
| 特性 | SNARK (Groth16/PLONK) | STARK |
|---|---|---|
| 信任設置 | 需要(某些類型) | 不需要 |
| 密碼學假設 | 需要「配對友好」的橢圓曲線 | 只依賴哈希函數(量子安全) |
| 證明大小 | 很小(~200 bytes) | 較大(~100 KB) |
| 驗證速度 | 很快 | 相對慢一些 |
| 信任設置類型 | 電路特定(Groth16)或通用(PLONK) | N/A |
STARK 的核心技術是 FRI(Fast Reed-Solomon IOP of Proximity)。FRI 是一種「多項式承諾」,只依賴哈希函數,而不依賴橢圓曲線。這讓 STARK 在理論上是「量子安全」的。
缺點是證明尺寸大得多——這在某些應用場景下是不可接受的。
在以太坊上的應用
ZK-SNARK 和 ZK-STARK 在以太坊生態中有大量應用:
zkSync(ZK Rollup):
- 使用 SNARK(基於 PLONK 的自定義變體)
- 將大量交易「打包」成一個證明
- 主鏈只驗證這個簡潔的證明
StarkEx:
- 使用 STARK
- 為 dYdX、ApeX 等交易平台提供 Layer 2 結算
Aztec:
- 使用 PLONK
- 專注於隱私交易
Polygon zkEVM:
- 使用多種零知識證明技術
- 目標是完全相容 EVM 的 zkRollup
zkSync Era 的 Boojum:
- 使用 Hash-based PLONK(無需信任設置)
- 實現了顯著的性能提升
這些項目的共同目標是:在保證安全性的前提下,把大量計算「搬到」鏈下執行,只在鏈上留下一個簡潔的證明。
常見的密碼學術語對照
| 英文術語 | 繁體中文術語 | 說明 |
|---|---|---|
| Prover | 證明者 | 聲明知道秘密的一方 |
| Verifier | 驗證者 | 檢查證明是否有效的一方 |
| Witness | 見證人/私密輸入 | Prover 知道的秘密值 |
| Circuit | 電路 | 計算問題的電路表示 |
| Constraint | 約束 | 電路中每個門必須滿足的條件 |
| R1CS | 一階約束系統 | 標準化的約束描述格式 |
| QAP | 二次算數程序 | R1CS 的多項式打包版本 |
| Polynomial Commitment | 多項式承諾 | 對多項式的「綁定承諾」 |
| CRS | 公共參考字串 | 信任設置生成的公共參數 |
| Pairing | 配對 | 橢圓曲線上的特殊雙線性映射 |
| Trusted Setup | 信任設置 | 生成 CRS 的初始化過程 |
| Succinctness | 簡潔性 | 證明短小、驗證快速 |
| Zero-Knowledge | 零知識 | 不洩漏 witness 的特性 |
| Non-interactive | 非互動式 | 不需要來回對話 |
| Knowledge Soundness | 知識可靠性 | 必須真正知道 witness 才能證明 |
結語:複雜但優雅
ZK-SNARK 的數學基礎確實很複雜——橢圓曲線配對、多項式代數、密碼學承諾,這些都需要時間消化。但我個人覺得,最令人驚嘆的是這些模塊如何組合成一個完整的系統。
Prover 拿著一個秘密 witness,經過一系列「數學魔術」,最終生成一個「看起來像隨機垃圾」的證明。Verifier 拿著這個垃圾,加上公開輸入,用幾次配對運算就能確認 Prover 確實知道那個秘密。整個過程沒有洩漏任何關於 witness 的資訊。
這種「看起來像魔術但實際上是數學」的感覺,大概就是密碼學最吸引人的地方吧。
如果你對這個話題有興趣,建議從實際動手開始——嘗試用 ZoKrates 或 Circom 寫一個簡單的 ZK 電路,看看「證明」長什麼樣子。數學推導和實際程式之間的對照,往往能幫你建立更直觀的理解。
延伸閱讀:
- Vitalik 的《Quadratic Arithmetic Programs》部落格文章
- PLONK 原始論文(Gabizon, Williamson & Ciobotaru, 2019)
- Halo2 技術文件(Zcash Foundation)
橢圓曲線配對:ZK-SNARK 的密碼學基石
如果你想深入理解 ZK-SNARK,橢圓曲線配對是不可繞過的一環。很多人在這裏就被數學符號嚇跑了,但別擔心,我會用最直觀的方式解釋這套機制在 ZK-SNARK 中到底起了什麼作用。
橢圓曲線密碼學基礎
橢圓曲線(Elliptic Curve)是滿足以下方程式的所有點的集合:
y² = x³ + ax + b
其中 a 和 b 是常數,且 4a³ + 27b² ≠ 0(這個條件確保曲線沒有奇點)。
在密碼學中,我們通常在一個有限域 Fₚ(p 是一個大質數)上定義這條曲線,也就是把 x 和 y 限制在 0 到 p-1 的範圍內,做算術運算時取模 p。
曲線上定義了一個「加法」運算,規則很特別:對於兩個不同的點 P 和 Q,連線與曲線的第三個交點關於 x 軸的對稱點就是 P+Q。如果 P = Q,那就是 P 點的切線與曲線的交點。
這個加法運算有一個關鍵性質:封閉性(封閉在曲線上)、結合律、交換律、單位元(無窮遠點 O)、逆元(每個點都有負元)。換句話說,曲線上的點在這個加法下構成一個阿貝爾群。
我們稱 n 個 P 相加為 [n]P,其中 n 是一個整數。對於某些特殊選擇的曲線和基點 G,存在一個質數 n,使得 [n]G = O(無窮遠點),而 k < n 時 [k]G ≠ O。這樣的 n 就是這個點的階(order)。
橢圓曲線密碼學的安全性基於「離散對數問題」:給定 G 和 Q = [k]G,要在計算上求出 k 是非常困難的。目前已知最快的演算法(baby-step giant-step 或 Pollard's rho)需要大約 O(√n) 次運算,對於足夠大的 n 來說是天文數字。
橢圓曲線上的配對
配對(Pairing)是橢圓曲線上的一種特殊雙線性映射。說「雙線性」是什麼意思呢?
設 G₁、G₂、Gₜ 是三個群(通常我們用加法記號表示 G₁ 和 G₂,用乘法記號表示 Gₜ),階都是 n。一個配對 e: G₁ × G₂ → Gₜ 滿足以下性質:
- 雙線性:對於任意 P₁, P₂ ∈ G₁, Q₁, Q₂ ∈ G₂:
- e(P₁ + P₂, Q₁) = e(P₁, Q₁) · e(P₂, Q₁)
- e(P₁, Q₁ + Q₂) = e(P₁, Q₁) · e(P₁, Q₂)
推論:e([a]P, [b]Q) = e(P, Q)^{ab}
- 非退化性:如果 P ≠ O₁(這裏 O₁ 是 G₁ 的單位元),存在 Q ∈ G₂ 使得 e(P, Q) ≠ 1ₜ(這裏 1ₜ 是 Gₜ 的單位元)。反之亦然。
- 可計算性:對於任意 P ∈ G₁, Q ∈ G₂,存在高效算法計算 e(P, Q)。
在 ZK-SNARK 中常用的配對是「Weil 配對」和「Tate 配對」的變體。實務上,BN128 曲線(又稱 BN254)是最流行的選擇,因為它提供了高效可計算的配對運算。
BN128 曲線定義為:
- G₁: E(Fₚ) 上階為 n 的子群,p = 21888242871839275222246405745257275088548364400416034343698204186575808495617
- G₂: E'(Fₚ²) 上階為 n 的子群
- Gₜ: Fₚ¹² 的乘法子群,階為 n
配對 e: G₁ × G₂ → Gₜ 可以用 Miller 演算法高效計算。
配對在 Groth16 驗證中的作用
回到 Groth16 的驗證等式:
e(πA, πB) = e(C̃, G₂) · e(H̃, Z̃)
為什麼配對這個「魔法」能讓驗證成立?
讓我們展開推導:
根據 Groth16 的設置,存在秘密值 α, β, γ, δ, τ,而 proving key 和 verification key 分別包含:
- PK: [α·G₁, β·G₁, γ·G₁, δ·G₁, {τⁱ·G₁}, {τⁱ·G₂}]
- VK: [β·G₂, γ·G₂, δ·G₂, {τⁱ·G₂}]
Prover 計算:
- πA = A(α)·G₁
- πB = B(β)·G₂
- πC = C(γ)·G₁
- πH = H(τ)·G₁
驗證者檢查:
e(A(α)·G₁, B(β)·G₂) = e(α·G₁, β·G₂) · e(C(γ)·G₁, γ·G₂) · e(H(τ)·G₁, δ·G₂) / e(γ·G₁, δ·G₂) · e(δ·G₁, Z(τ)·G₂)
使用配對的雙線性性質:
左邊 = e(G₁, G₂)^{A(α)·B(β)}
右邊 = e(G₁, G₂)^{α·β + C(γ)·γ + H(τ)·δ - C(γ)·γ - Z(τ)·δ}
= e(G₁, G₂)^{α·β + H(τ)·δ - Z(τ)·δ}
如果電路正確執行(即 H(τ) = (A(τ)·B(τ) - C(τ))/Z(τ)),那麼:
A(τ)·B(τ) - C(τ) = H(τ)·Z(τ)
A(α)·B(β) - C(γ) = α·β + H(τ)·δ - Z(τ)·δ
代回去,左邊等於右邊,驗證成立!
這個推導展示了配對的核心作用:它讓我們可以「混合」來自 G₁ 和 G₂ 的秘密值,在不洩漏秘密的情況下驗證它們之間的代數關係。
橢圓曲線的安全性考量
在實際部署 ZK-SNARK 系統時,選擇合適的曲線和安全參數非常重要:
曲線選擇:
- BN128:最成熟,配對效率高,但 2020 年後密碼學社群對其安全性有了更多了解
- BLS12-381:現在更推薦的選擇,提供約 128 位元安全等級
- BW6-761:用於 PLONK 的常見選擇,支援更大的有限域
攻擊向量:
- 離散對數攻擊:依賴橢圓曲線的硬度
- MOV 攻擊:利用配對把離散對數問題「降維」到有限域
- 特殊構造攻擊:對某些不當選擇的曲線有效
一個好的系統設計會選擇經過充分審計的曲線參數,並避免自創曲線。
多項式承諾:數學原理與深度推導
多項式承諾是 ZK-SNARK 中另一個核心密碼學原語。讓我們深入理解它的數學基礎。
承諾方案的基本定義
一個承諾方案包含三個階段:
- 承諾階段:Prover 對一個值 v 計算 c = Commit(v; r),其中 r 是隨機的盲化因子。c 是公開的承諾,綁定(binding)於 v 但隱藏(hiding)了 v 的具體內容。
- 打開階段:Prover 公開 (v, r),Verifier 驗證 c = Commit(v; r)。
- 額外功能:某些承諾方案允許 Prover 證明「承諾的內容滿足某些性質」,而不透露內容本身。這就是「多項式承諾」。
對多項式承諾來說:
- 承諾:Prover 對一個多項式 f(x) 計算Commitment C。
- 打開:Prover 可以證明「在某個點 z,f(z) = y」。
- 驗證:Verifier 檢查證明,接受或拒絕。
理想情況下,承諾具有:
- 約束性(Binding):無法對兩個不同的多項式產生相同的承諾
- 隱藏性(Hiding):從承諾無法推斷出多項式內容
- 同態性(Homomorphic):承諾可以線性組合
KZG 承諾的完整推導
KZG(Kate-Zaverucha-Goldberg)承諾是目前最流行的多項式承諾方案。讓我們一步步推導它的工作原理。
設置:
- 選擇一個橢圓曲線群 G₁、G₂,階為 n,存在雙線對 e: G₁ × G₂ → Gₜ。
- 選擇秘密值 τ ∈ Fₙ,並「毀滅」——任何人都不會知道 τ。
- 計算 powers of τ: G₁: [τ·G₁, τ²·G₁, ..., τᵈ·G₁], G₂: [τ·G₂],其中 d 是多項式最大degree。
- 發布 CRS = {τⁱ·G₁} ∪ {τ·G₂}。
承諾:
對於多項式 f(x) = f₀ + f₁x + f₂x² + ... + fₖxᵏ:
Commit(f) = f(τ)·G₁ = (f₀ + f₁τ + f₂τ² + ... + fₖτᵏ)·G₁
= f₀·G₁ + f₁·(τ·G₁) + f₂·(τ²·G₁) + ... + fₖ·(τᵏ·G₁)
這個承諾是「同態的」:Commit(f) + Commit(g) = Commit(f+g)。
打開:
Prover 要證明 f(z) = y。
定義商多項式 q(x) = (f(x) - y) / (x - z)。這是一個次數最多為 k-1 的多項式(如果 f 的次數 ≤ k)。
Prover 計算 q(x) 並發布 Commitment(Cq) = q(τ)·G₁。
Verifier 需要驗證:f(τ) - y = q(τ) · (τ - z)。
使用配對:
e(Commit(f) - y·G₁, G₂) ?= e(Cq, τ·G₂ - z·G₂)
根據配對的雙線性:
左邊 = e(f(τ)·G₁ - y·G₁, G₂) = e(G₁, G₂)^{f(τ) - y}
右邊 = e(q(τ)·G₁, (τ-z)·G₂) = e(G₁, G₂)^{q(τ)·(τ-z)}
如果 f(z) = y,那麼 (f(x) - y) 確實可以被 (x - z) 整除,所以等式成立。
如果 f(z) ≠ y,則 (f(x) - y) 無法被 (x - z) 整除——Verifier 可以通過這個檢測發現欺騙。
安全性分析:
- 約束性:給定 Commit(f),無法找到另一個 g 使得 g(τ) = f(τ)。這依賴於 τ 的秘密性。
- 隱藏性:由於 τ 是未知的,從 Commit(f) 無法推斷 f(x) 的係數。
信任設置的脆弱性:
如果有人在設置時洩漏了 τ,那麼她可以構造假的 Commitments 和 Proofs。例如,給定任意 y,可以聲稱「f(z) = y」並構造對應的 q(x)。
這就是為什麼 Groth16 需要「多方計算」(MPC)信任設置儀式——只要有一個參與者是誠實的,τ 就無法被完全洩漏。
從 KZG 到多點開啟
基本的 KZG 只支援單點開啟。在實際 ZK-SNARK 中,我們常常需要同時開啟多個點。
假設 Prover 要證明 f(z₁) = y₁, f(z₂) = y₂, ..., f(zₘ) = yₘ。
定義差值多項式:
D(x) = f(x) - Σᵢ [yᵢ · Lᵢ(x)]
其中 Lᵢ(x) 是拉格朗日基多項式,在 zⱼ 處取值為 1(j=i)或 0(j≠i)。
定義零化多項式:
Z(x) = (x - z₁)(x - z₂)...(x - zₘ)
Prover 計算 q(x) = D(x) / Z(x)。
Verifier 驗證:
e(Commit(f) - Σ yᵢ·Commit(Lᵢ), G₂) = e(Commit(q), τ·G₂)
這個結構允許一次配對檢查驗證多個點的開啟,大幅提高效率。
對數空間 KZG 的進階技巧
當多項式很大時(例如百萬級別的係數),直接傳送整個 Commitment 不現實。這時我們需要一些進階技巧:
批量開啟:如果多個 Provers 對同一個 CRS 承諾了不同的多項式,Verifier 可以要求他們提供「隨機線性組合」的開啟,而不是分別開啟每個多項式。
防禦性采樣:Verifier 選擇隨機值 β,Prover 計算 Commitment(f + β·g) 和對應開啟。如果單個承諾正確,則組合承諾正確的概率極高。
可驗證延遲函數(VDF):某些應用需要證明「這個承諾是在過去某個時間點生成的」。這可以通過結合 VDF 來實現,讓承諾的計算本身需要可驗證的時間投入。
以太坊上的 ZK 應用:技術架構深度解析
zkSync Era 的 Boojum 升級
zkSync Era 在 2024 年進行了重大升級,推出了 Boojum——一個基於 Hash-based PLONK 的新證明系統。這個升級的目標是消除對「可信設置」的依賴。
Boojum 的核心創新:
- 使用 Goldilocks 有限域(p = 2⁶⁴ - 2³² + 1),硬體友好
- 採用 Poseidon 和 Rescue 哈希函數,電路友好
- 證明者(Prover)使用新的 GPU 加速演算法
實際數據:升級後,zkSync Era 的交易費用降低了 10 倍,而 Prover 成本降低了 100 倍。這對於 L2 的經濟可持續性來說意義重大。
Polygon zkEVM 的證明系統
Polygon zkEVM 採用的是「zk-STARK + Recursive SNARK」的混合架構:
- 首先,用 STARK 證明每個區塊的正確性(無需信任設置)
- 然後,用 SNARK 來「壓縮」這些 STARK 證明
這種設計結合了兩種技術的優點:STARK 的透明性和量子安全性,加上 SNARK 的簡潔性和快速驗證。
Aztec Connect:隱私 + 互操作性
Aztec 是以太坊上最專注隱私的 Layer 2 項目。Aztec Connect 允許用戶在保持隱私的情況下與以太坊公有 DeFi 協議交互。
技術上,Aztec 使用 PLONK 的自定義變體(Turbo-PLONK + PLOOKUP),支援定制的「查找表」約束。這讓某些計算(如位元運算)比標準 PLONK 更高效。
隱私的代價是更高的證明成本。Aztec 的交易費用比普通 L2 高出 5-10 倍。但對於高價值隱私交易來說,這個成本可能是值得的。
結語:從理論到實踐
ZK-SNARK 的世界深不可測——橢圓曲線密碼學、抽象代數、計算複雜性理論,這些看起來不相關的數學領域在這裏交匯成一幅優雅的圖景。
我自己研究這塊內容的體會是:不要試圖一次理解所有東西。先搞懂「證明者可以向驗證者證明某個計算正確執行,同時不透露輸入」這個直覺,再逐步深入具體的數學構造。
實踐是最好的老師。我强烈建議你:
- 用 ZoKrates 或 Circom 寫一個簡單的電路(比如「我知道一個秘密數的平方是 X」)
- 實際生成一個證明
- 在本地驗證這個證明
- 把這個證明部署到測試網上
當你親眼看到一個證明只有幾百 bytes,卻能在瞬間驗證複雜計算的正確性時,你會對這項技術的威力有更深的體會。
ZK-SNARK 和 ZK-STARK 正在改變我們對「隱私」和「信任」的理解。在一個日益數位化的世界中,這項技術的意義遠遠超出了加密貨幣——它是構建未來互聯網隱私和安全的基石。
延伸閱讀:
- Vitalik Buterin《Quadratic Arithmetic Programs》
- Gabizon, Williamson & Ciobotaru《PLONK: Permutations over Lagrange-bases for Oecumenical Noninteractive arguments of Knowledge》
- Zcash Foundation《Halo2 Design》
- Bootle《Efficient Zero-Knowledge Arguments without Trusted Setup》
COMMIT: Add elliptic curve pairing mathematics and polynomial commitment deep dive
相關文章
- ZK-SNARK 電路設計數學推導進階教程:從理論到 Circom/Noir 實作 — 本文深入探討 ZK-SNARK 電路設計的數學推導與實作細節,是對現有 ZK-SNARK 數學推導文章的進階補充。我們從電路複雜度理論出發,詳細推導約束系統的數學原理,並提供完整的 Circom 與 Noir 實作範例。涵蓋電路複雜度邊界、橢圓曲線群運算、配對函數、R1CS 到 QAP 轉換、查找表約束、Merkle 樹驗證等核心技術。
- ZK-SNARK 完整學習路徑:從基礎數學到 Circom/Noir 電路設計再到實際部署 — 本學習路徑提供零知識證明從理論基礎到實際開發的完整指南。從離散數學、群論、有限域運算開始,深入橢圓曲線密碼學和配對函數,再到 Groth16、PLONK 等主流證明系統的數學推導,最終落實到 Circom 和 Noir 兩種電路描述語言的實戰開發。涵蓋有限域運算、多項式承諾、KZG 方案、信任設置等核心主題,提供從基礎到部署的完整學習地圖。
- ZK-SNARKs 數學推導完整指南:從零知識證明基礎到 Groth16 協議工程實踐 — 本文從工程師的視角出發,提供零知識證明數學基礎的完整推導。從密碼學安全假設出發,逐步建立零知識證明的理論框架,深入分析 zk-SNARKs 的核心協議——包括 Groth16、PLONK 與 Halo2 的設計原理與數學推導,並提供完整的程式碼範例說明如何在以太坊上實際部署零知識證明系統。
- Privacy Pool ZK-Proof 驗證合約完整實作指南:從電路設計到 Solidity 部署 — 本文深入探討 Privacy Pool 系統中零知識證明(ZKP)驗證合約的完整實作流程。我們從密碼學基礎出發,詳細解釋 Groth16 和 PLONK 兩種主流零知識證明系統的原理,提供完整的 Circom 電路代碼範例,並展示如何將這些電路部署到以太坊區塊鏈上進行驗證。涵蓋 Merkle 樹驗證電路、承諾方案實現、完整隱私池合約代碼、以及可信設置教學。
- 以太坊零知識證明完整實作指南:從密碼學基礎到 zk-SNARKs/STARKs 智能合約部署 — 零知識證明(Zero-Knowledge Proof,ZKP)是現代密碼學中最具革命性的技術之一,其核心特性——在不透露任何額外資訊的情況下證明陳述的正確性——為區塊鏈隱私保護和可擴展性帶來了前所未有的可能性。本文從以太坊開發者的視角出發,深入探討零知識證明的密碼學基礎、zk-SNARKs 與 zk-STARKs 的技術差異、主流實作框架(如 Circom、ZoKrates、Groth16、PLONK)的使用方法,以及如何在以太坊上部署零知識證明智能合約。我們將提供完整的程式碼範例,涵蓋從電路設計、證明生成到鏈上驗證的整個流程,同時深入分析每個環節的 Gas 消耗、安全考量與最佳實踐。
延伸閱讀與來源
- zkSNARKs 論文 Gro16 ZK-SNARK 論文
- ZK-STARKs 論文 STARK 論文,透明化零知識證明
- Aztec Network ZK Rollup 隱私協議
- Railgun System 跨鏈隱私協議
這篇文章對您有幫助嗎?
請告訴我們如何改進:
評論
發表評論
注意:由於這是靜態網站,您的評論將儲存在本地瀏覽器中,不會公開顯示。
目前尚無評論,成為第一個發表評論的人吧!