Zksnarks筆記: from programe to QAP
源自: https://medium.com/@VitalikButerin/quadratic-arithmetic-programs-from-zero-to-hero-f6d558cea649
對於如下的程式,我們需要通過三步得到最終的QAP
- programe => gates
- gates => R1CS
- R1CS => QAP
def qeval(x):
y = x**3
return x + y + 5
1 Flattening program => gates
只包含兩種形式 x = y
和 x = y (op) z
(where op can be +, -, *, /
and y and z can be variables, numbers or themselves sub-expressions)
// 每一行可以理解為1個Gate
sym_1 = x * x
y = sym_1 * x
sym_2 = y + x
~out = sym_2 + 5
2 Gates to R1CS
An R1CS is a sequence of groups of three vectors (a, b, c)
, and the solution
to an R1CS is a vector s
s . a * s . b - s . c = 0
The length of each vector
is equal to the total number of variables in the system
上面的例子中, 有6個變數 '~one', 'x', '~out', 'sym_1', 'y', 'sym_2'
(~one
和~out
是必須的), 因此向量的長度為6
第一個gate對應的 (a,b,c)
為
a = [0, 1, 0, 0, 0, 0] // x b = [0, 1, 0, 0, 0, 0] // x c = [0, 0, 0, 1, 0, 0] // sym_1
第二個gate對應的 (a,b,c)
為
a = [0, 0, 0, 1, 0, 0] // sym_1
b = [0, 1, 0, 0, 0, 0] // x
c = [0, 0, 0, 0, 1, 0] // y
第三個gate對應的為
a = [0, 1, 0, 0, 1, 0] // y + x
b = [1, 0, 0, 0, 0, 0] // ~one
c = [0, 0, 0, 0, 0, 1] // sym_2
第四個gate對應的為
a = [5, 0, 0, 0, 0, 1] // 5 * ~one + sym_2
b = [1, 0, 0, 0, 0, 0] // ~one
c = [0, 0, 1, 0, 0, 0] // ~out
同時滿足這四個gate的(a,b,c)
的s . a * s . b - s . c = 0
的解 s
為
[1, 3, 35, 9, 27, 30]
將所有的a, b, c放到一起
A
[0, 1, 0, 0, 0, 0]
[0, 0, 0, 1, 0, 0]
[0, 1, 0, 0, 1, 0]
[5, 0, 0, 0, 0, 1]
B
[0, 1, 0, 0, 0, 0]
[0, 1, 0, 0, 0, 0]
[1, 0, 0, 0, 0, 0]
[1, 0, 0, 0, 0, 0]
C
[0, 0, 0, 1, 0, 0]
[0, 0, 0, 0, 1, 0]
[0, 0, 0, 0, 0, 1]
[0, 0, 1, 0, 0, 0]
3 R1CS to QAP
QAP form: implements the exact same logic except using polynomials
instead of dot products
多項式的階取決於有多少gate, 這裡有4個gate, 所以為3階
A polynomials
[-5.0, 9.166, -5.0, 0.833] // 0.833 * x**3 — 5*x**2 + 9.166*x - 5, 經過(1,0) (2,0) (3,0) (4,5)這幾個點
[8.0, -11.333, 5.0, -0.666] // 經過點 (1,1) (2,0) (3,1) (4,0)
[0.0, 0.0, 0.0, 0.0] // 經過點(1,0) (2,0) (3,0) (4,0) , 上面A的第三列
[-6.0, 9.5, -4.0, 0.5]
[4.0, -7.0, 3.5, -0.5]
[-1.0, 1.833, -1.0, 0.166] // 經過點 (1,0) (2,0) (3,0) (4,1), 上面A的第6列
B polynomials
[3.0, -5.166, 2.5, -0.333]
[-2.0, 5.166, -2.5, 0.333]
[0.0, 0.0, 0.0, 0.0]
[0.0, 0.0, 0.0, 0.0]
[0.0, 0.0, 0.0, 0.0]
[0.0, 0.0, 0.0, 0.0]
C polynomials
[0.0, 0.0, 0.0, 0.0]
[0.0, 0.0, 0.0, 0.0]
[-1.0, 1.833, -1.0, 0.166]
[4.0, -4.333, 1.5, -0.166]
[-6.0, 9.5, -4.0, 0.5]
[4.0, -7.0, 3.5, -0.5]
為什麼要轉成QAP?
instead of checking the constraints in the R1CS individually, we can now check all of the constraints at the same time
by doing the dot product check on the polynomials.
A(x) = A . s = [43.0, -73.333, 38.5, -5.166]
B(x) = B . s = [-3.0, 10.333, -5.0, 0.666]
C(x) = C . s = [-41.0, 71.666, -24.5, 2.833]
A . s * B . s — C . s:
t = [-88.0, 592.666, -1063.777, 805.833, -294.777, 51.5, -3.444]
Z = (x - 1) * (x - 2) * (x - 3) * (x - 4) (因為有4個gate)
Z = [24, -50, 35, -10, 1]
h = t / Z = [-3.666, 17.055, -3.444] // 因為t(1),t(2),t(3),t(4)都為0, 所以t(x)能夠整除Z(x)
我們現在不用分別計算t(1), t(2), t(3), t(4)是否為0, 轉而判斷t(x)能否整除Z(x)
回顧:我們將R1CS的
s . a * s . b - s . c = 0
的驗證 轉化為 判斷QAP的t(x)在對應取值處(這裡為1,2,3,4)是否為0, 然後再轉化為t(x)能否整除Z(x)