ZK 증명 시스템 구조 (공통된 큰 틀)
┌────────────────────────────────────┐
│ Arithmeticization │ → 문제를 다항식으로 바꿈
├────────────────────────────────────┤
│ Commitment Scheme │ → 다항식 or 증거를 커밋
├────────────────────────────────────┤
│ Low-Degree Testing / Constraints │ → 다항식이 "좋은 것"인지 확인
├────────────────────────────────────┤
│ Proof + Verification │ → 증명 생성하고 검증
└────────────────────────────────────┘
| 단계 | SNARK (ex. PLONK, Groth16) | STARK |
|---|---|---|
| 표현 | R1CS, Arithmetic circuits | Trace table → 다항식 |
| 커밋 | KZG commitment, Merkle Tree | Merkle tree (RS-encoded) |
| LDT | Algebraic Consistency (PLONK), QAP | FRI (Reed-Solomon 기반) |
| 증명 | Groth16, PLONK proof 등 | STARK proof (FRI 포함) |
핵심 구조 :
1. 계산을 trace로 만든다.
2. trace -> 다항식으로 변환한다.
3. 이 다항식이 저차수라는 것을 증명한다 (FRI)
4. Merkle root로 다항식에 커밋하고, 일부 점만 검사한다.
| Step | x | y |
|---|---|---|
| 0 | 1 | 1 |
| 1 | 1 | 2 |
| 2 | 2 | 3 |
| 3 | 3 | 5 |
| ... |
계산 과정을 위 처럼 정리하고, 이런 테이블을 각 컬럼마다 하나의 다항식으로 변환
저차수 다항식을 만드는 이유는
여기서 아래 세가지 등장
FRI는 STARK에서 다항식이 low-degree인지 증명하기 위한 핵심 프로토콜
역할 :
어떻게 가능한가:
이 반복 과정을 Split-and-Fold로 최적화
"여러 개의 constraint 다항식을 하나로 합쳐서 검증하자."
모든 다항식을 하나의 다항식으로 합친다 :
Folded_P(x) = α₁·P₁(x) + α₂·P₂(x) + ... + α_k·P_k(x)
alpha_i 가 랜덤하게 고른 challengeRedd-Solomon과 Split-and-Fold가 전부 FRI에 포함되는 최적화 기법임
STARK 프로토콜 전체 흐름
├── Trace 생성
├── AIR Constraint → Quotient Polynomial들
│ ├── Quotient_1(x), Quotient_2(x), ...
│ └── 👉 Split-and-Fold 적용
├── 하나의 Folded Polynomial → Low-degree 증명 (FRI)
AIR = "알고리즘을 다항식으로 바꾸는 중간 표현"
STARK에서의 R1CS 또는 PLONK의 Gate system에 해당
AIR 구성
├── Trace Table (계산 상태)
├── Transition Constraints (시간 흐름 규칙)
├── Boundary Constraints (초기/최종 조건)
└── Public Inputs/Outputs
동작 방식
1. 프로그램 실행 결과 → Trace로 구성
2. 규칙(Constraints) 정의 → 다항식화
3. 전체 다항식이 low-degree → FRI로 증명
예: 피보나치 계산 (x[n+2] = x[n+1] + x[n])
| t | reg0 | reg1 |
|---|------|------|
| 0 | 1 | 1 |
| 1 | 1 | 2 |
| 2 | 2 | 3 |
| 3 | 3 | 5 |
| 4 | 5 | 8 |
t에서 t+1로 갈 때 지켜야 하는 관계식reg0[t+1] = reg1[t]
reg1[t+1] = reg0[t] + reg1[t]
↓
(transition constraint 다항식 형태):
f₀(x⋅g) - f₁(x) = 0
f₁(x⋅g) - f₀(x) - f₁(x) = 0
여기서 x는 시점이고, g는 도메인 상의 primitive root (시간 이동)
예: reg0[0] = 1, reg1[0] = 1
reg0[0] - 1 = 0
reg1[0] - 1 = 0
AIR의 핵심은:
"trace가 주어진 규칙을 만족하는지"를
다항식들이 low-degree인지 확인함으로써 증명하는 것
이때 각 constraint를 다음과 같이 표현함:
코드 복사
P(x) = transition_constraint(x) * mask(x)
mask(x)는 특정 점에서만 0이 아닌 다항식P(x) 만듦→ 이 P(x)가 실제로 low-degree인지 FRI로 증명하면 끝
x[n], x[n+1]f₀(x⋅g) = f₁(x) f₁(x⋅g) = f₀(x) + f₁(x)`
(이 두 식이 전체 domain에서 만족되면 OK)
f₀(1) = 1 f₁(1) = 1`