Advanced Cryptography Program 2026 / Week 4 自習ノート
Week 4 の講義は「証明」と「ゼロ知識性」を分けて扱います。前半は そもそも証明とは何か、なぜ検証者は全部を読まずに納得できるのかを、 計算複雑性の言葉で置き直します。後半は現代のゼロ知識証明を 算術化・コミットメント・証明システムの 3 部品に分解し、 GKR・STARK・PLONK を同じ物差しで並べます。
このノートでは、講義と同じトイ計算 f = (x₁ + x₂) + (x₃·x₄) を
3 通りに翻訳して手で計算し、そのうえで 嘘の証明者が何回に 1 回すり抜けるかを実測します。
SumCheck の嘘は 121 通り中 21 通りしか通らない。改ざんしたトレースは商多項式が消える。
ゲート制約を全部満たしても配線が違えば大積で落ちる。この 3 つが「健全性」の手触りです。
出発点
先週の課題は、楕円曲線の上で 「秘密鍵 x を知っている」ことを、x を見せずに納得させる 3 手の会話を実装するものでした。数式が多くて全体が見えにくかったので、 まず誰が何を持っていて、何を送り、何を確かめたのかだけを 1 枚にします。
公開されているもの: 生成点 G、公開鍵 P = x·G (x は証明者だけが知る)
証明者 検証者
r をその場の乱数で選ぶ
R = r·G ── R を送る ──▶
◀── e を送る ── e をその場の乱数で選ぶ
s = r + e·x ── s を送る ──▶ s·G == R + e·P ? を計算して比べる
検証者は x を知りません。それでも右辺 R + e·P は、受け取った R と、
自分で選んだ e と、公開されている P だけで計算できます。左辺 s·G も、
受け取った s と公開の G だけで計算できます。両辺が同じ点になるのは、
s の中に本当に x が入っているときだけです(s·G = (r + e·x)·G = R + e·P)。
x が漏れないのは、s = r + e·x の x が毎回違う乱数 r で覆われているから。
そして r を 2 回使い回すと、2 本の s の差から x が割り出せてしまう。
先週の「nonce 再利用で鍵が漏れる」テストはこれを実演していました。
今週の問いは、ここから一段抽象に上がります。「x を知っている」を渡せたなら、 「この計算全体を正しく実行した」も同じように渡せないか。 そのために「証明」という言葉そのものを、いったん分解します。
講義の最初の問い — 電子署名とゼロ知識証明の違いは?
同じ数式を、違う目的で使っています。
上の 3 手で、検証者の e を「ハッシュ値 e = H(R, P, メッセージ)」に置き換えると、
会話が要らなくなり、(R, s) だけを渡せば誰でも検証できます。これが Schnorr 署名です
(Fiat–Shamir 変換)。
署名が渡すのは「この鍵の持ち主が、このメッセージに同意した」という第三者に見せられる証拠。 ゼロ知識証明が渡すのは「この主張は真である」という納得で、しかも主張の裏にある秘密 (x や、計算の中身)は渡さない。署名は「知識の証明」の特殊な使い方だ、と見ることができます。
前提について
このノートは Week 3 の 3 手(上の図)が読めれば進めます。有限体・多項式の割り算・ ラグランジュ補間は本文で数値を入れて追いますが、不安があれば 土台編と Week 3 ノートの 後半(多項式と commitment の地図)を先にどうぞ。
この頁の構成
前提 1
「証明」は数学の専門用語ではなく、日常で毎日やっていることです。年齢を示すために身分証を出す。 経費のために領収書を出す。ここに数学もゼロ知識も要りません。講義はまず、この日常の証明を 5 つのパートに分解するところから始めます。
この分解をすると、日常の証明の弱点が見えます。身分証は発行元を信頼しているし、 領収書は偽造できるし、アリバイは証言者を信頼している。 検証方法のどこかに「誰かを信じる」が入っています。
数学的証明が優れているのは、検証方法が機械的で、証明者を信じる必要がないことです。 「s·G と R + e·P を計算して比べる」は、誰がやっても同じ結果になります。 検証者は証明者の人柄も、計算環境も、発行元も信じなくてよい。式だけを信じればよい。
ただし数学的証明にも 1 つ、日常の証明と同じ弱点が残っています。 証明が長いと、検証にも時間がかかることです。 1 万行の計算が正しいと確かめるのに 1 万行読み直すなら、証明者と検証者の手間は同じ。 「弱い検証者が、強い証明者の主張を、短時間で確かめる」ためには、 読まなくても納得できる仕掛けが要ります。それが次の節です。
Week 3 の 3 手を 5 パートに当てはめると
今週はこの 5 パートのうち「証明対象」を「x を知っている」から「計算 f を正しく実行した」に広げます。 証明方法と検証方法は、そのぶん複雑になります。
前提 2
「証明が長いと検証も長い」を破るために、まず計算にも難しさがあることを 物差しにします。難しさは、入力サイズ n に対して手数がどう増えるかで測ります。
時間(ステップ数)、空間(メモリ)、それに証明の話で効いてくる通信量と
回路サイズ。n が 2 倍になったとき手数が 2 倍で済むのが O(n)、
2 乗になるのが O(n²)、2 倍ごとに倍々になるのが O(2ⁿ)。
Week 3 の double-and-add がまさにこの話でした。k·G を「G を k 回足す」と
O(k)、2 進で見て倍々に作ると O(log k)。secp256k1 の k ≈ 2²⁵⁶ では
前者は終わらず、後者は 10 ms で終わります。同じ答えでも、手数の増え方が違えば
「できる/できない」が変わる。
P は、多項式時間(O(n)、O(n²)、…)で
答えを見つけられる問題の集まり。NP は、答えの候補(証拠、witness)を
渡されたときに、多項式時間で正しいと確かめられる問題の集まりです。
講義の例はグラフの 3 彩色でした。「隣り合う頂点が同じ色にならないように 3 色で塗れるか」。
塗り方を見つけるのは総当たりだと 3ⁿ 通り。
塗り方を確かめるのは辺の数だけ色を見比べればよい。
実際に講義のグラフ(ピーターセングラフ、頂点 10・辺 15)で数えました。
総当たりで試した塗り方 : 59049 通り(3¹⁰) そのうち条件を満たすもの : 120 通り 1 つの塗り方を検証する手数 : 15 回(辺ごとに「両端が違う色か」を見るだけ)
ここが今週いちばん大事な一文です。NP は「証拠を渡せば、弱い検証者でも速く確かめられる」問題の集まり。 つまり NP は、最も標準的な証明システムそのものです。証明者は無限に強くてよい(塗り方を見つける)。 検証者は多項式時間しか使えない(塗り方を確かめる)。Week 3 の「x を知っている」も、 「回路を正しく実行した」も、全部この形に収まります。
NP のままでは、証拠(塗り方、計算の記録)を丸ごと渡すので、検証は証拠の長さに比例します。 ここに 3 つの材料を足します。
PCP 定理は驚くべき主張です。NP の証拠は、書き方を工夫すれば 「検証者がランダムに数か所だけ読めば十分」な形に書き直せる。1 万行の証明を 1 万行読む必要はない。 ただし証明者があとから書き換えられないことが条件で、それを保証するのが「オラクル」—— 現実にはコミットメント(Merkle 木や KZG)です。先週の commitment は、ここで使うために出てきました。
対話型と非対話型の使い分け(講義の Q)。対話型は「特定の検証者を、その場で」納得させるのに向き、 非対話型(Fiat–Shamir で e をハッシュにしたもの)は「誰でも、あとから、オンチェーンで」検証できる。 先週の Schnorr → 署名の変換と、まったく同じ手です。
前提 3
完全性(Completeness): 主張が真なら、正直な証明者は必ず通る。 健全性(Soundness): 主張が偽なら、どんな証明者も(ほぼ)通らない。 Week 3 で「simulator の会話も受理される」を見たとき、この 2 つに加えて ゼロ知識性(会話から秘密が漏れない)を分けて考えました。今週も同じ 3 本柱です。
今週新しく加わるのがスケーラビリティの軸です。証明を作る時間、検証する時間、証明のサイズ、鍵のサイズ。 講義の問い「証明者向けと検証者向けの最適化、どちらが重要?」には両方の答えがあります。 検証者は「多数・弱い端末・オンチェーンでガス代を払う」ので、検証コストと証明サイズが小さいほど使い道が広がる。 一方で証明者のコストが実用範囲に収まらなければ、そもそも証明が作れない。 スキームの違いは、ほぼこのトレードオフをどこに置くかの違いです。
「主張の真偽」と「証明可能性」を一致させる
スライドの右側の図は、この 2 つを上下に置いて双方向の矢印で結んでいました。 完全性は「真 → 証明できる」、健全性は「証明できる → 真」。両方向が揃って初めて、 「証明が通った」を「主張が真」と読み替えてよい。
ただし現代のスキームの健全性は確率的です。嘘の証明者は「たまに」通る。 その確率が 2⁻¹⁰⁰ なら実用上ゼロ。このノートのラボは体を小さく(F₁₁、F₁₇)してあるので、 その「たまに」を数えられます。
部品表
講義は GKR・STARK・PLONK の 3 つを、毎回同じ 3 つの箱で説明していました。 箱の名前を先に固定しておくと、どのスキームも「箱の中身が違うだけ」に見えてきます。
| GKR(2008) | STARK(2018) | PLONK(2019) | |
|---|---|---|---|
| 系統 | IP ベース | IOP ベース ① | IOP ベース ②(多項式 IOP) |
| A. 算術化 | レイヤー付き算術回路 → 多重線形多項式(MLE) | 実行トレース → AIR(遷移多項式と制約多項式) | ゲート表 → Plonkish(11 本の一変数多項式) |
| B. コミットメント | 元論文ではなし(後の Virgo/Libra が FRI/KZG を導入) | Merkle 木ベースの多項式コミットメント | KZG(楕円曲線・ペアリング)ベースの多項式コミットメント |
| C. 証明システム | SumCheck をレイヤーごとに | FRI(商多項式の低次数性) | KZG の開示証明 + ゼロテストと大積 |
| ゼロ知識化の手 | 多項式のマスキング + コミットメント | ブラインド多項式 + Merkle のソルト | ブラインド多項式(witness・配線・商) |
このノートの読み方
以下、3 スキームとも講義と同じトイ計算 f(x₁,x₂,x₃,x₄) = (x₁ + x₂) + (x₃·x₄)、
入力 (3, 1, 2, 4) を使います。GKR は F₁₁ で答え 4 + 8 = 12 ≡ 1、
STARK と PLONK は F₁₇ で答え 12。同じ計算が、3 通りの多項式に翻訳されるのを見てください。
各節の最後に「壊した実測」を置きました。嘘の証明者がどこで、どのくらいの確率で落ちるかを数えています。
スキーム 1 / GKR
GKR は「証明者は強い、検証者は弱い」を一番素直に形にしたスキームです。 回路の出力側から入力側へ 1 レイヤーずつ、「このレイヤーの値は正しい」という主張を 「1 つ下のレイヤーのある 1 点の値は正しい」という主張に置き換えていきます。 置き換えの道具が SumCheck です。
L₀ : y = y₀ + y₁ 出力: 1 L₁ : y₀ = x₁ + x₂ , y₁ = x₃ · x₄ 値: 4, 8 L₂ : x₁, x₂, x₃, x₄ ∈ F₁₁ 入力: 3, 1, 2, 4 ゲートに 2 進の番地をつける: L₁ の 2 個 → 0, 1 L₂ の 4 個 → 00, 01, 10, 11 f(3,1,2,4) = (3 + 1) + (2 · 4) = 12 ≡ 1 (mod 11)
Week 1 の算術回路そのものです。違いは、レイヤーごとに区切って 「各レイヤーの値の表」と「レイヤー間の配線の表」を別々に扱うこと。 前者は秘密(witness)、後者は公開(回路の形)です。
レイヤー 2 の値の表は「番地 (z₁,z₂) → 値」で 00→3, 01→1, 10→2, 11→4。
これを、0/1 の格子点では表と一致し、格子の外まで滑らかに伸ばした唯一の多項式にします。
各変数について 1 次(線形)なので「多重線形」です。
W̃₂(z₁,z₂) = 3(1−z₁)(1−z₂) + 1(1−z₁)z₂ + 2z₁(1−z₂) + 4z₁z₂
= 3 − z₁ − 2z₂ + 4z₁z₂ ← 展開して整理(mod 11 で係数は 3, 10, 9, 4)
W̃₁(z) = 4(1−z) + 8z = 4 + 4z ← レイヤー 1 の表 {0→4, 1→8}
W̃₀( ) = 1 ← レイヤー 0(変数なし)
なぜ 0/1 の外まで伸ばすのか。あとで検証者が 0 でも 1 でもないランダムな点で値を聞くからです。 表のままなら「番地 2」に値はありませんが、多項式にしておけば W̃₁(2) = 4 + 8 = 12 ≡ 1 が定まる。 ランダムな点で聞けるようにすることが、少ない手数で嘘を見つける仕掛けの土台になります。
配線の表も多項式にします。レイヤー 0 のゲートは「レイヤー 1 の番地 0 と番地 1 を足す」でした。 それを式にしたのが g₀ です。
g₀(a, b) = (1−a) · b · ( W̃₁(a) + W̃₁(b) )
↑ (a,b) = (0,1) のときだけ 1、それ以外の格子点では 0
W̃₀ = Σ_{a,b∈{0,1}} g₀(a,b) = g₀(0,1) = 1·(4 + 8) = 12 ≡ 1 ✓
ここで主張の形が決まります。「レイヤー 0 の値は 1 である」は 「ある多項式 g₀ を 0/1 の全組み合わせで足すと 1 になる」という形に書き直された。 レイヤーが深くなっても、主張は必ずこの「格子点全部の和」の形になります。 格子点は変数の数を k とすると 2ᵏ 個。検証者はこれを全部足したくない。
変数を 1 つずつ「潰し」ます。各ラウンドで証明者は一変数多項式を送り、 検証者は2 点の値を足すだけで前ラウンドと辻褄が合うか見て、 ランダムな点でその多項式を評価し、それを次ラウンドの「主張」にします。
主張: Σ_{a,b} g₀(a,b) = 1
ラウンド 0(a を潰す)
証明者 → p₁(x) = Σ_{b∈{0,1}} g₀(x,b) = g₀(x,0) + g₀(x,1)
= 0 + (1−x)·(W̃₁(x) + W̃₁(1)) = (1−x)(12 + 4x)
= 12 − 8x − 4x² ≡ 1 + 3x + 7x² (mod 11)
検証者: p₁(0) + p₁(1) = 1 + 11 = 12 ≡ 1 … 主張と一致 ✓
r₁ = 2 を選ぶ → p₁(2) = 1 + 6 + 28 = 35 ≡ 2 ← 次の主張は「g₀(2, b) の b についての和 = 2」
ラウンド 1(b を潰す)
証明者 → p₂(y) = g₀(2, y) = (1−2)·y·(W̃₁(2) + W̃₁(y)) = −y(16 + 4y)
= −5y − 4y² ≡ 6y + 7y² (mod 11)
検証者: p₂(0) + p₂(1) = 0 + 13 = 13 ≡ 2 … 前ラウンドの p₁(2) と一致 ✓
r₂ = 3 を選ぶ → p₂(3) = 18 + 63 = 81 ≡ 4
最後(自分で 1 点だけ計算する)
検証者: g₀(2, 3) = (1−2)·3·(W̃₁(2) + W̃₁(3)) = −3·(1 + 5) = −18 ≡ 4 … p₂(3) と一致 ✓
検証者がやったこと: 各ラウンドで 2 点の値の足し算と 1 点の評価、最後に g₀ を 1 回だけ評価。 4 項の和(本物なら 2ᵏ 項)を一度も足していません。 それで納得できる理由は、嘘をつくなら多項式そのものを変えるしかなく、 違う多項式は 0/1 以外のほとんどの点で値が違うから。ランダムな r で聞けば高い確率でずれが出ます。
ただし最後の 1 行に注意。検証者は g₀(2,3) を計算するのに W̃₁(2) と W̃₁(3) が要ります。 これはレイヤー 1 の値の表(秘密)から作る多項式なので、検証者は自分では計算できません。 そこで証明者が「W̃₁(2) = 1、W̃₁(3) = 5 です」と主張し、その 2 つが次のレイヤーで確かめる新しい主張になります。 「レイヤー 0 の和」が「レイヤー 1 の 2 点の値」に置き換わった——これが「1 段降りる」の正体です。
2 点のまま降りると、次は 4 点、その次は 8 点と倍々に増えます。 そこで2 点を通る直線を引き、W̃₁ をその直線上に制限した一変数多項式 qを証明者に送らせ、 直線上のランダムな 1 点だけを次の主張にします。
2 点 u = 2, v = 3 を通る直線: l(t) = (1−t)·2 + t·3 = 2 + t
証明者 → q(t) = W̃₁(l(t)) = 4 + 4(2 + t) = 12 + 4t ≡ 1 + 4t
検証者: q(0) = 1 = 主張された W̃₁(2) ✓, q(1) = 5 = 主張された W̃₁(3) ✓
r = 4 を選ぶ → q(4) = 17 ≡ 6 → 新しい主張は「W̃₁(6) = 6」の 1 つだけ
この繰り返しで入力レイヤーまで降りると、最後の主張は「W̃₂(ある点) = ある値」になります。 入力は公開なので、検証者はこれだけは自分で計算して照合できる(入力が秘密ならコミットメントの開示で代える)。 回路の深さぶんだけラウンドを重ねて、最後に 1 回だけ本物の値に触る。これが GKR の全体です。
壊した実測 — 嘘の主張は、何回に 1 回通るか
証明者が「レイヤー 0 の値は 5 だ」と嘘をついたとします。ラウンド 0 の検査
p₁(0) + p₁(1) = 5 を通すには、本物の p₁ に 4·(1−x) を足した偽物を送ればよい
(0 で 4、1 で 0 なので和が 4 増える)。ラウンド 1 も同じ手で辻褄を合わせられます。
ずれが露見するのは最後の 1 点だけ。
嘘の主張 5 に対して、検証者の (r₁, r₂) を 11 × 11 = 121 通り全部試した結果: 受理されてしまう組 : 21 通り (r₁ = 1 または r₂ = 1 のとき — 偽物の足し分 (1−x) が 0 になる点) 嘘が露見する組 : 100 通り → 嘘がすり抜ける確率 21 / 121 ≈ 17%。体を F₁₁ から 2²⁵⁴ 元の体にすると 2 / 2²⁵⁴ ≈ 0。
健全性は「絶対に落ちる」ではなく「ランダムな点で聞くから、ほぼ落ちる」。体の大きさがその確率を決めます。 下のラボで、どの (r₁, r₂) が嘘を見逃すかを地図にしました。
ラボ 1
レイヤー 0 の SumCheck を F₁₁ で回します。あなたが検証者で、r₁ と r₂ を選びます。 証明者を「嘘」にすると、主張した値だけを変えて辻褄合わせの多項式を送ってきます。 右の地図は、いまの主張に対して 121 通りの (r₁, r₂) のどれが受理してしまうかです。
—
—
やりとり
スキーム 2 / STARK
STARK は計算を回路ではなくプログラムの実行記録(トレース)として見ます。 各ステップの状態を表に書き、「隣り合う行の関係が正しい」を多項式の等式にし、 最後はある多項式が別の多項式で割り切れるかという 1 つの問いに落とします。
f(x₁,x₂,x₃,x₄) = (x₁ + x₂) + (x₃·x₄) ∈ F₁₇, f(3,1,2,4) = 12 t a m y ← a: 加算結果, m: 乗算結果, y: 最終結果 0 0 0 0 初期状態 1 4 0 0 a ← x₁ + x₂ = 4 2 4 8 0 m ← x₃ · x₄ = 8 3 4 8 12 y ← a + m = 12
回路とトレースの違い。回路は「値がどう繋がるか」の図、トレースは「時間ごとに状態がどう変わるか」の表。 CPU の命令実行や VM のように「同じ規則を何万ステップも繰り返す」計算は、トレースのほうが自然に書けます。 制約は「行と次の行の関係」だけで済み、ステップ数が増えても制約の種類は増えない。
行番号 t を、そのまま数字ではなく ω の t 乗に置きます。F₁₇ で ω = 4 は
4⁰=1, 4¹=4, 4²=16, 4³=13, 4⁴=1 と 4 回で 1 に戻る(位数 4)ので、
4 行の表にぴったりです。この 4 点 H = {1, 4, 16, 13} が評価ドメイン。
各列を、H の 4 点を通る 3 次以下の多項式に補間する(ラグランジュ補間): A(X) = 3 − X − X² − X³ A(1)=0, A(4)=4, A(16)=4, A(13)=4 ✓ M(X) = 4 + 6X + 7X³ M(1)=0, M(4)=0, M(16)=8, M(13)=8 ✓ Y(X) = 3 + 12X + 14X² + 5X³ Y(1)=0, Y(4)=0, Y(16)=0, Y(13)=12 ✓
なぜ t を ω^t にするのか。「次の行」が X → ωX というただの掛け算になるからです。 A(ωX) は「1 行あとの a の値」を表す多項式になり、行と次の行の関係を A(X) と A(ωX) の式で書けます。 そして H が「ω の冪」であることが、次のステップの消滅多項式を X⁴ − 1 という短い形にします。
規則(遷移制約):
X = ω⁰ の行で A(ωX) − 4 = 0 (次の a は x₁+x₂ = 4)
X = ω¹ の行で M(ωX) − 8 = 0 (次の m は x₃·x₄ = 8)
X = ω² の行で Y(ωX) − A(X) − M(X) = 0 (次の y は a + m)
S_i(X) を「H の中で ω^i でだけ 1、他では 0」の選択多項式として 1 本に足す:
C(X) = S₀(X)(A(ωX) − 4) + S₁(X)(M(ωX) − 8) + S₂(X)(Y(ωX) − A(X) − M(X))
= 2 − 5X − 5X² − 2X⁴ + 5X⁵ + 5X⁶ (mod 17 では 2 + 12X + 12X² + 15X⁴ + 5X⁵ + 5X⁶)
C(1) = C(4) = C(16) = C(13) = 0 ← H の全点で 0。ここが「トレースが正しい」の言い換え
スライドの「= 0」は「多項式として 0」ではなく「H の全点で 0」の意味です。 C(X) 自体は 6 次の立派な多項式で、H の外では 0 になりません。 「H の全点で 0」を検証者がどう確かめるか——4 点なら全部評価すればよいが、 2²⁰ 行のトレースでは無理。次の一手が STARK の要です。
多項式 C が点 h で 0 なら、C は (X − h) で割り切れる(因数定理)。
H の全点で 0 なら、全部の (X − h) の積で割り切れる。
その積が消滅多項式 Z_H(X) = Π_{h∈H}(X − h) = X⁴ − 1 です
(H が 1 の 4 乗根の集合だから、こんなに短い)。
Q₀(X) = C(X) / Z_H(X) = C(X) / (X⁴ − 1) = 5X² + 5X − 2 余り 0 検算: (X⁴ − 1)(5X² + 5X − 2) = 5X⁶ + 5X⁵ − 2X⁴ − 5X² − 5X + 2 = C(X) ✓
問いが入れ替わりました。「C は H の全点で 0 か」→「Q₀ = C / Z_H は多項式か(割り切れて余りが出ないか)」。 さらに Q₀ が多項式なら次数は deg C − 4 = 2 以下のはず。 だから検証者が確かめるべきことは 「証明者が持っている Q₀ は、次数 2 以下の多項式か」。 トレースが 1 か所でも間違っていれば、C は H のどこかで 0 にならず、Z_H で割り切れず、 Q₀ は多項式にならない(点ごとに値は作れても、低い次数の多項式にはならない)。
証明者は Q₀ を、H より広い評価ドメイン(例: g = 2 の冪、8 点 {1,2,4,8,16,15,13,9})で評価し、
その値を葉にした Merkle 木を作り、根だけを検証者に渡します。
検証者があとで「g³ の値を見せて」と言えば、証明者は葉と経路を出す。根が固定されているので値は差し替えられません。
ここが「オラクル ≈ コミットメント」の実体です。PCP の「検証者が証明の一部だけ読む」を実現するには、 証明者が質問を見てから証明を書き換えられないことが必要。Merkle 根がそれを保証する。 ハッシュだけでできるので信頼設定が要らず(透明)、量子計算にも比較的強い。
Q₀ を偶数次と奇数次に分けると Q₀(X) = Q_even(X²) + X·Q_odd(X²)。
検証者がランダムな β を送り、証明者は Q₁(Y) = Q_even(Y) + β·Q_odd(Y) を作ってまたコミット。
次数が半分になるので、繰り返すと定数になります。
Q₀(X) = 5X² + 5X − 2 = (5X² − 2) + X·5 → Q_even(Y) = 5Y − 2, Q_odd(Y) = 5
β₁ = 3: Q₁(Y) = (5Y − 2) + 3·5 = 5Y + 13 次数 2 → 1
β₂ = 5: Q₂ = 13 + 5·5 = 38 ≡ 4 次数 1 → 0(定数。これは平文で送る)
クエリ(検証者が x = 8 を選ぶ):
証明者が Q₀(8) = 1 と Q₀(−8) = Q₀(9) = 6 を Merkle 経路つきで開示
検証者: Q_even(8²) = (Q₀(8) + Q₀(9)) / 2 = 7·9 ≡ 12
Q_odd(8²) = (Q₀(8) − Q₀(9)) / (2·8) = −5·16 ≡ 5
→ Q₁(8²=13) は 12 + 3·5 = 27 ≡ 10 のはず。Q₁ の Merkle 開示 5·13 + 13 = 78 ≡ 10 と一致 ✓
x と −x の 2 点だけで偶奇部分が復元できるのがミソです(x² が同じだから)。 各ラウンドで数か所クエリすれば、「本当に半分の次数の多項式に折り畳まれているか」が Schwartz–Zippel の確率で確かめられる。検証者は Q₀ を丸ごと読まない。
壊した実測 — トレースを 1 マス書き換える
y₃ を 12 → 13 に改ざん(他はそのまま)
C(X) は H の上で [0, 0, 1, 0] ← X = ω² の行の規則 y₃ = a₂ + m₂ が破れた
C(X) を X⁴ − 1 で割った余り = 13 + 4X + 13X² + 4X³ ← 0 でない。商多項式が存在しない
それでも「点ごとに C/Z_H を作って 8 点分」を証明者が送ったとして、その 8 点を補間すると
次数 7 の多項式になる(正直なら次数 2)→ FRI の低次数テストが落ちる
a を全部 5、y₃ を 13 にした「自己整合」な改ざん(4+8=12 の代わりに 5+8=13)
C(X) は H の上で [1, 0, 0, 0] ← 今度は X = ω⁰ の行の規則 a₁ = x₁ + x₂ = 4 が破れる
→ 公開入力から決まる 4 が制約に焼き込まれているので、内部だけ整合させても逃げられない
改ざんの場所がどこでも、必ず「割り切れない」に現れる。検証者はどのマスが変わったかを知らなくてよい。
ラボ 2
F₁₇ のトレース(公開入力 3, 1, 2, 4)のマスを直接書き換えられます。 書き換えるたびに、遷移多項式 → 制約多項式 → Z_H で割った商と余り → コセット上の低次数テスト、 そして商が存在するときは FRI の折り畳みまで計算し直します。
1 つ注意があります。講義のトイ AIR が縛っているのは a₁ = x₁+x₂、m₂ = x₃·x₄、
y₃ = a₂+m₂ の 3 本だけです。制約の無いマス(y₁ など)は書き換えても通ります——
Week 1 で見たアンダー制約そのもの。実物の AIR は境界制約(初期状態が 0)と「値を保持する」制約
(A(ωX) − A(X) = 0 など)を足して全マスを縛ります。「y₁ を 5 に」を押して確かめてください。
| t | X = ω^t | a | m | y |
|---|
—
遷移多項式 → 制約多項式 → 商
—
FRI
—
スキーム 3 / PLONK
PLONK は回路をゲート 1 個 = 表の 1 行として並べます。各行に「入力左・入力右・出力」の 3 つの値と、「このゲートは足し算か掛け算か」を表す係数を置き、行の中の関係と、行をまたぐ配線を 別々の多項式の等式で確かめます。
witness(秘密) selector(公開: 回路の型) wiring(公開: 配線)
L R O Q_L Q_R Q_M Q_O Q_C σ_L σ_R σ_O
gate 0 (+) 3 1 4 1 1 0 −1 0 ω⁰k₀ ω⁰k₁ ω⁰k₂ →(L,gate2)
gate 1 (×) 2 4 8 0 0 1 −1 0 ω¹k₀ ω¹k₁ ω¹k₂ →(R,gate2)
gate 2 (+) 4 8 12 1 1 0 −1 0 ω²k₀→(O,gate0) ω²k₁→(O,gate1) ω²k₂
ゲート方程式(全行で 0 になるべき):
Q_L·L + Q_R·R + Q_M·L·R + Q_O·O + Q_C = 0
gate 0: 3 + 1 + 0 − 4 + 0 = 0 ✓ gate 1: 0 + 0 + 8 − 8 + 0 = 0 ✓ gate 2: 4 + 8 + 0 − 12 + 0 = 0 ✓
1 本の式で足し算も掛け算も表せるのがセレクターの役目です。(Q_L,Q_R,Q_M,Q_O) = (1,1,0,−1) なら L + R − O = 0 で足し算、(0,0,1,−1) なら L·R − O = 0 で掛け算。回路の形はセレクターに、値は witness に分かれる。 11 本のベクトルはそれぞれ、行番号 ω⁰, ω¹, ω² を通る一変数多項式にラグランジュ補間されます。
ゲート方程式は行の中しか見ません。gate 2 の L に 4 でなく 5 を書き、O を 13 にしても、
5 + 8 − 13 = 0 で gate 2 の式は通ってしまう。
行をまたぐ「同じ値であるべき場所」を縛るのがコピー制約です。
各マスに番地 ω^行 · k_列(k₀, k₁, k₂ は列を区別する定数)をつけ、
「同じ値であるべきマス」を巡回置換 σ で入れ替えます。すると
「マスの (値, 番地) の集まり」と「(値, σ(番地)) の集まり」が、集合として同じことが配線の正しさそのもの。
集合の一致を 1 個の数で確かめる(大積 / grand product): 検証者がランダムな β, γ を選ぶ Π_マス (値 + β·番地 + γ) と Π_マス (値 + β·σ(番地) + γ) が等しいか F₁₀₁、ω = 10、k = (1,2,3)、β = 5、γ = 7 で計算すると(行ごとの積 f_i / g_i と累積): gate 0: f = 51, g = 4 累積 51/4 = 38 gate 1: f = 87, g = 21 累積 38·87/21 = 42 gate 2: f = 19, g = 91 累積 42·19/91 = 1 ← 一周して 1 に戻る = 集合が一致
累算器 p(X) は「p(ω⁰) = 1、p(ω^{i+1}) = p(ω^i)·f_i/g_i」という行ごとの漸化式で、 最後に 1 に戻ることを p(ωX)·g(X) − p(X)·f(X) = 0(H の全点で)というゼロテストにして、 STARK と同じく Z_H で割った商を作ります。「H の全点で 0 ⇔ Z_H で割り切れる」は、ここでも同じ道具です。
Setup(信頼設定): 秘密の τ を選び、SRS = { τ·g₁, τ²·g₁, …, τᵈ·g₁, g₂, τ·g₂ } を公開して τ は捨てる
Commit: Com_f = f(τ)·g₁ ← τ を知らなくても Σ cᵢ·(τⁱ·g₁) で作れる(Week 3 の「スカラー倍」)
Open(α で開く): q(X) = (f(X) − f(α)) / (X − α) ← f(α) が本当の値なら割り切れる(また因数定理)
Com_q = q(τ)·g₁
Verify: f(τ) = (τ − α)·q(τ) + f(α) を、ペアリングで「指数の中の掛け算」として確認
e(Com_f − f(α)·g₁, g₂) = e(Com_q, τ·g₂ − α·g₂)
証明が短い理由: 多項式が何次でも、コミットメントは楕円曲線の点 1 個(数十バイト)。 信頼設定が要る理由: τ を誰かが覚えていれば偽のコミットメントが作れる。だから MPC 儀式で「誰も τ を知らない」状態にする。 Week 3 ノート後半の「f(X) = X² + 1 について f(2) = 5 を開く」が、この Open の最小例です。
インプット制約: 公開入力に対応するマスの値を KZG の開示証明で見せる
ゲート制約: f(X) = Q_L(X)L(X) + Q_R(X)R(X) + Q_M(X)L(X)R(X) + Q_O(X)O(X) + Q_C(X) が H で 0
→ Q(X) = f(X) / Z_H(X) の存在を、ランダム点での開示で確かめる
コピー制約: 累算器 p(X) について p(ωX)g(X) − p(X)f(X) が H で 0(p(ω⁰) = 1 も)
→ 同じくゼロテスト → 商多項式 → ランダム点での開示
検証者の仕事は最終的に「数個のランダム点で、数個の多項式の値が等式を満たすか」だけになり、 ペアリングの計算が数回で済む。証明サイズも検証時間も回路の大きさによらない(O(1))。 そのぶん証明者は 11 本の多項式を作って FFT と MSM を回すので重い。ここがトレードオフです。
壊した実測 — ゲート制約は全部通し、配線だけ違う witness
gate 2 を (L, R, O) = (5, 8, 13) にする ゲート方程式: gate 0: 0 ✓ gate 1: 0 ✓ gate 2: 5 + 8 − 13 = 0 ✓ ← 3 行とも通ってしまう コピー制約: gate 0 の O = 4 ≠ gate 2 の L = 5 ✗ 大積(F₁₀₁, β = 5, γ = 7): 左辺 88 ≠ 右辺 75 ✗ β, γ を 10100 通り全部試すと、この偽 witness を受理してしまう組は 681 通り(≈ 6.7%) → 実際の 254 ビット体では ≈ 9 / 2²⁵⁴ ≈ 0
ゲート制約は「各行が正しい型で計算されている」しか言わない。配線がなければ、行ごとに勝手な値を置いても通る。 2 種類の制約が揃って初めて「この回路をこの入力で実行した」になります。
ラボ 3
witness の 9 マス(F₁₇)を書き換えられます。行ごとのゲート方程式、2 本のコピー制約、 そして β, γ を変えながらの大積(F₁₀₁)を同時に計算します。 ゲート制約が全部緑でも大積が赤になる表を作ってみてください。
| 型 | L | R | O | セレクター |
|---|
—
ゲート制約(行の中)
コピー制約(行をまたぐ)
大積 — 累算器の 1 周
—
ゼロ知識性
ここまでの 3 スキームは、実はゼロ知識ではありません。検証者は「主張が真」と納得できますが、 途中で開示された多項式の値(Q₀(8) = 1 など)は witness から作られた値なので、集めれば witness の情報が漏れます。 講義の後半はこれを塞ぐ手です。
f̃(X) := f(X) + Z_H(X)·R(X) R(X) は証明者が毎回選ぶランダム多項式 例(F₁₇、f = Y(X) = 3 + 12X + 14X² + 5X³、R(X) = 6 + 2X): f̃(X) = 14 + 10X + 14X² + 5X³ + 6X⁴ + 2X⁵ H の上: X=1: (0, 0) X=4: (0, 0) X=16: (0, 0) X=13: (12, 12) ← (f, f̃) 一致。Z_H が 0 だから H の外: X=2: (4, 1) X=3: (11, 2) X=5: (1, 6) ← 別の値。R によって毎回変わる
検証者が値を聞くのは H の外のランダムな点でした(Schwartz–Zippel のため)。
そこでは f̃ の値は R で覆われていて、f の情報を含まない。
そして制約の検査は H の上でしか見ていないので、f を f̃ に差し替えても「H の全点で 0」は保たれる。
Week 3 の s = r + e·x で x を r が覆っていたのと同じ構図で、
覆う量が数 1 個から多項式 1 本に増えただけです。
STARK: 遷移多項式と制約多項式。FRI で開示する回数ぶんのランダムネスが要り、 Merkle の葉にもソルトを混ぜる(葉のハッシュから値を総当たりされないため)。 PLONK: witness 多項式、配線(累算器)多項式、各商多項式。
講義の Q「なぜセレクター多項式はブラインド化しないのか」。セレクターは回路の型で、 もともと公開情報だから隠す理由がない。それどころかブラインドすると次数が上がって証明者のコストだけ増える。 隠すべきは witness とそれから派生する多項式だけ。「何が秘密で何が公開か」を 11 本のベクトルの段階で 分けておいたことが、ここで効きます。
GKR は SumCheck の途中で p₁(x), p₂(y) を平文で送るので、そのままでは W̃ の情報が漏れます。
そこで (1) 回路の値の多項式をコミットし、(2) マスク用の多変数多項式 R をコミットし、
(3) f + R に対して SumCheck を回し、(4) 終盤に V_original = V_total − V_random と引き算で相殺し、
(5) 多項式評価はコミットメントの開示証明(Merkle + FRI など)で代える。
講義の Q「どちらか片方だけではなぜダメか」。マスキングだけだと、 証明者が R をあとから都合よく選び直せる(相殺の式で辻褄を合わせられる)ので、R は先にコミットして固定する必要がある。 コミットメントだけだと、SumCheck で送る一変数多項式そのものが W̃ の情報を持ったまま。 「隠す」(マスク)と「固定する」(コミット)は別の仕事で、両方が要ります。
同じ物差しで並べる
スライドの各所にあった「Q. 各種計算量、通信量、証明サイズは?」の答えのページは、配布版では伏せられています (ワークショップで考える問いのため)。以下はこのノートの整理で、講義の公式解答ではありません。 n は回路サイズまたはトレース長です。
| GKR | STARK | PLONK(KZG) | |
|---|---|---|---|
| 証明者の計算量 | O(n)(Libra 以降。元論文は多項式時間) | O(n log n)(FFT)— 定数はやや重い | O(n log n) FFT + 楕円曲線の MSM — 定数が重い |
| 検証者の計算量 | O(深さ · log n) + 入力の評価 | O(log² n)(FRI のクエリ) | O(1)(ペアリング数回) |
| 証明サイズ / 通信量 | O(深さ · log n) 個の体の元。対話型のまま使うことが多い | O(log² n)。数十〜数百 KB | O(1)。数百バイト |
| 信頼設定 | 不要 | 不要(透明) | 要(universal SRS。回路ごとには不要) |
| 使う仮定 | なし(情報理論的) + コミットメント次第 | ハッシュ関数のみ → 量子計算に比較的強い | ペアリング(離散対数系)→ 量子計算に弱い |
| ゼロ知識 | そのままでは無し。マスク + コミットで付ける | ブラインド多項式 + ソルト | ブラインド多項式 |
| 得意な形 | 浅くて幅の広い回路、構造の規則的な回路(行列積など) | 長い繰り返し(VM の実行) | 任意の回路。カスタムゲート・lookup で拡張しやすい |
| 子孫 | Virgo / Libra(FRI・KZG を導入)、Jolt(部分的に) | Redshift(AIR → Plonkish)、zkSTARK(DEEP FRI) | Halo2(KZG → IPA)、Plonky2/3(Plonkish/AIR + FRI) |
まとめのスライドにあった分類図(Thaler の教科書の図)を言葉にすると、実用 SNARK は大きく 2 系統です。 「多項式 IOP + 多項式コミットメント」——今日の 3 つは全部これで、 IOP 側に IP ベース(GKR)・MIP ベース(Spartan など)・定数ラウンド多項式 IOP(Marlin、PLONK)があり、 コミットメント側に IOP ベース(FRI)・離散対数ベースで透明なもの(Bulletproofs、IPA)・ペアリングベース(KZG)がある。 もう 1 系統が「線形 PCP + ペアリング」で、Groth16 がここ。
大枠と構成要素は共通、組み合わせはさまざま。同じ名前でも論文と実装で細部が違う (Halo2 は PLONK の算術化に KZG でなく IPA を組む、Plonky2 は Plonkish に FRI を組む)。 だから「どの算術化・どのコミットメント・どの証明システムか」を 3 つ言えれば、初見のスキームでも読める。 それが今週の一番の持ち帰りです。
共通して何度も出てきた道具
ラグランジュ補間: 表を多項式にする(W̃、A/M/Y、11 本のベクトル)。
因数定理と消滅多項式: 「H の全点で 0」⇔「Z_H で割り切れる」(STARK の商、PLONK のゼロテスト、KZG の開示)。
Schwartz–Zippel: 違う多項式はランダムな点でほぼ違う値(SumCheck、FRI、大積、KZG)。
ランダム線形結合: 複数の検査を 1 本にまとめる(線形削減、FRI の β、大積の β・γ)。
道具は 4 つ。並べ方が 3 通り。
ワークショップの準備
課題: AI エージェントの運用実績(例: タスク完了率)を、サービスの機密データ(顧客データ)を渡さずに、 外部の損保会社に証明するシステムを設計する。検討すべきは、指標と測定・証明方法、 機密データの秘匿方法、トラストモデル、現実的なトレードオフ。
今週の 5 パートに当てはめると、証明者はサービス事業者、検証者は損保会社、 証明対象は「期間 T のタスク完了率 ≥ 95%」のような命題。 問題は証明方法——「完了率」の元になるログは顧客データを含み、渡せない——と、 検証方法——損保会社は事業者の自己申告を信じたくない——です。
設計の分岐は、まず「何を信頼するか」で決まります。
そのうえで候補を並べます。(a) ZK 証明: ログの Merkle 根(第三者が署名)を公開入力に、 完了率の計算を回路にして証明。STARK 系なら信頼設定なし、PLONK 系なら証明が短くオンチェーン検証向き。 (b) MPC: 事業者と損保会社で秘密計算——Week 2 の道具。ZK と違って両者が同時に参加する必要がある。 (c) TEE: 計測プログラムを enclave で走らせ、attestation を渡す。証明ではなくハードウェアへの信頼。 (d) 監査 + NDA: 第三者監査人が中身を見る。技術ではなく契約で秘匿。
「not ZK」が正解の場合も多い。指標が粗く、頻度が低く、監査人を置けるなら (d) が最も安い。 ZK が効くのは「継続的・自動・第三者に見せたくない・検証者が多い」とき——今週の 「検証者向けの最適化」の話がそのまま判断基準になります。
議論で使える 3 つの問い
1. 何がゼロ知識で守られ、何は守られないか。完了率 95% という数字そのものは漏れる。それで十分か。分布は要るか。
2. 健全性の穴はどこか。ログの改ざん(証明の前)、指標の定義のずれ(回路の外)、nonce や乱数の使い回し(Week 3)。
3. コストは誰が払うか。証明者(事業者)が毎月証明を作るコスト。検証者(損保)の検証コスト。回路を書く人件費。
3 部品(算術化・コミットメント・証明システム)と 5 パート(証明者・方法・対象・検証・検証者)を 表に書いてから話すと、議論が具体になります。
検問クイズ
読んだだけでは定着しない。ここではあなたが検証者の席に座り、 SumCheck のラウンド、トレースの制約、ゲート表、FRI の折り畳みを審査する。問題は毎回その場で生成され、 判定は上のラボと同じ計算器が行う。3 回誤判定したら、その回は終了。
検問モードを選ぶ
誤答するとその場で解説が出る。分野を絞って弱点だけ潰すこともできる。
持ち帰り
読み終わったら答えられるはずのこと
・NP が「最も標準的な証明システム」だと言えるのはなぜか。証明者と検証者はそれぞれ何をするか。
・SumCheck で検証者が「和を足さない」のに納得できる理由を、Schwartz–Zippel の一言で言うと。
・「H の全点で 0」を「Z_H で割り切れる」に変えると、何が検証しやすくなるのか。
・PLONK でゲート制約とコピー制約の両方が要る理由を、壊れる witness の例つきで。
・ブラインド多項式 f + Z_H·R が、H の上で元の値を保つ理由と、外でランダムになる理由。
・KZG の信頼設定で「τ を捨てる」が必要な理由。
次に向けて
今週の 3 部品は、これ以降の週の地図です。新しいスキーム名が出てきたら、 算術化は何か・コミットメントは何か・証明システムは何かの 3 つを埋めてみてください。 埋まらない箱があれば、そこがそのスキームの新しさです。
そして Week 3 の Schnorr に戻ると、あれは算術化なし・コミットメント R = rG・証明システムはシグマプロトコルの 最小構成でした。今週の GKR / STARK / PLONK は、その「主張」を「x を知っている」から 「計算全体が正しい」に広げるために、3 つの箱を大きくしたものです。