R1CS to QAP¶
[1]:
%load_ext autoreload
%autoreload 2
Example¶
[2]:
# ref: https://medium.com/@VitalikButerin/quadratic-arithmetic-programs-from-zero-to-hero-f6d558cea649
from functools import partial
from klefki.zkp.r1cs import R1CS, mul
from klefki.zkp.qap import QAP
from klefki.curves.bns.bn128 import BN128FP as F
from klefki.algebra.rings import PolyRing
import ast
[3]:
# map int to field
ciphers = [1,2,3,4,5,6,7,8,9]
times = 5
@R1CS.r1cs(F)
def f(x, k, c):
y = x + c + k
return y ** 3
@R1CS.r1cs(F, globals())
def mimc(x, k):
for i in range(times):
c = ciphers[i]
x = f(x, k, c)
return x + k
[4]:
f.flatcode
[4]:
[['add', 'Sym::0', 'x', 'c'],
['add', 'y', 'Sym::0', 'k'],
['mul', 'Sym::1', 'y', 'y'],
['mul', '~out', 'Sym::1', 'y']]
[5]:
mimc.flatcode
[5]:
[['set', 'c', 1],
['add', 'Local<Rc(0)>Sym::0', 0, 2],
['add', 'Local<Rc(0)>y', 'Local<Rc(0)>Sym::0', 1],
['mul', 'Local<Rc(0)>Sym::1', 'Local<Rc(0)>y', 'Local<Rc(0)>y'],
['mul', 'x::0', 'Local<Rc(0)>Sym::1', 'Local<Rc(0)>y'],
['set', 'c::1', 2],
['add', 'Local<Rc(1)>Sym::0', 0, 2],
['add', 'Local<Rc(1)>y', 'Local<Rc(1)>Sym::0', 1],
['mul', 'Local<Rc(1)>Sym::1', 'Local<Rc(1)>y', 'Local<Rc(1)>y'],
['mul', 'x::2', 'Local<Rc(1)>Sym::1', 'Local<Rc(1)>y'],
['set', 'c::3', 3],
['add', 'Local<Rc(2)>Sym::0', 0, 2],
['add', 'Local<Rc(2)>y', 'Local<Rc(2)>Sym::0', 1],
['mul', 'Local<Rc(2)>Sym::1', 'Local<Rc(2)>y', 'Local<Rc(2)>y'],
['mul', 'x::4', 'Local<Rc(2)>Sym::1', 'Local<Rc(2)>y'],
['set', 'c::5', 4],
['add', 'Local<Rc(3)>Sym::0', 0, 2],
['add', 'Local<Rc(3)>y', 'Local<Rc(3)>Sym::0', 1],
['mul', 'Local<Rc(3)>Sym::1', 'Local<Rc(3)>y', 'Local<Rc(3)>y'],
['mul', 'x::6', 'Local<Rc(3)>Sym::1', 'Local<Rc(3)>y'],
['set', 'c::7', 5],
['add', 'Local<Rc(4)>Sym::0', 0, 2],
['add', 'Local<Rc(4)>y', 'Local<Rc(4)>Sym::0', 1],
['mul', 'Local<Rc(4)>Sym::1', 'Local<Rc(4)>y', 'Local<Rc(4)>y'],
['mul', 'x::8', 'Local<Rc(4)>Sym::1', 'Local<Rc(4)>y'],
['add', '~out', 'x::8', 'k']]
The format of a flatcode line is:
\[\left[Op, Out, S_a, S_b\right]\]
[24]:
mimc.var
[24]:
['~one',
'x',
'k',
'~out',
'c',
'Local<Rc(0)>Sym::0',
'Local<Rc(0)>y',
'Local<Rc(0)>Sym::1',
'x::0',
'c::1',
'Local<Rc(1)>Sym::0',
'Local<Rc(1)>y',
'Local<Rc(1)>Sym::1',
'x::2',
'c::3',
'Local<Rc(2)>Sym::0',
'Local<Rc(2)>y',
'Local<Rc(2)>Sym::1',
'x::4',
'c::5',
'Local<Rc(3)>Sym::0',
'Local<Rc(3)>y',
'Local<Rc(3)>Sym::1',
'x::6',
'c::7',
'Local<Rc(4)>Sym::0',
'Local<Rc(4)>y',
'Local<Rc(4)>Sym::1',
'x::8']
The format of variable is
\[[One, Input_0, \cdots, Input_n, Output, S_0, S_1, \cdots, S_n]\]
[25]:
assert len(mimc.A[0]) == len(mimc.var)
For each line of flatcodes, we have \(A_i.s \circ B_i.s == C_i.s\)
[26]:
s = mimc.witness(F(42))
s
[26]:
[BN128FP::0x1,
BN128FP::0x2a,
BN128FP::0x0,
BN128FP::0x1b,
BN128FP::0x1,
BN128FP::0x2,
BN128FP::0x3,
BN128FP::0x9,
BN128FP::0x1b,
BN128FP::0x2,
BN128FP::0x2,
BN128FP::0x3,
BN128FP::0x9,
BN128FP::0x1b,
BN128FP::0x3,
BN128FP::0x2,
BN128FP::0x3,
BN128FP::0x9,
BN128FP::0x1b,
BN128FP::0x4,
BN128FP::0x2,
BN128FP::0x3,
BN128FP::0x9,
BN128FP::0x1b,
BN128FP::0x5,
BN128FP::0x2,
BN128FP::0x3,
BN128FP::0x9,
BN128FP::0x1b]
[19]:
sum(mul(mimc.A[0], s)) * sum(mul(mimc.B[0], s)) == sum(mul(mimc.C[0], s))
[19]:
True
Gen QAP¶
[12]:
A, B, C = mimc.r1cs
[13]:
qap = QAP(A, B, C)
[14]:
w = mimc.witness(F(42))
w
[14]:
[BN128FP::0x1,
BN128FP::0x2a,
BN128FP::0x0,
BN128FP::0x1b,
BN128FP::0x1,
BN128FP::0x2,
BN128FP::0x3,
BN128FP::0x9,
BN128FP::0x1b,
BN128FP::0x2,
BN128FP::0x2,
BN128FP::0x3,
BN128FP::0x9,
BN128FP::0x1b,
BN128FP::0x3,
BN128FP::0x2,
BN128FP::0x3,
BN128FP::0x9,
BN128FP::0x1b,
BN128FP::0x4,
BN128FP::0x2,
BN128FP::0x3,
BN128FP::0x9,
BN128FP::0x1b,
BN128FP::0x5,
BN128FP::0x2,
BN128FP::0x3,
BN128FP::0x9,
BN128FP::0x1b]
[15]:
assert qap.verify(*qap.proof(F(112221), w))
[16]:
A, B, C, Z, H = qap.proof(F(112221), w)
PGHR13¶
[17]:
from klefki.curves.barreto_naehrig import bn128
from klefki.algebra.utils import randfield
from operator import add
from functools import reduce
A, B, C, Z = R1CS2QAP(*r1cs, F(42), field=F)
ECG = bn128.ECGBN128
G1 = bn128.ECGBN128.G1
G2 = bn128.ECGBN128.G2
e = bn128.ECGBN128.e
---------------------------------------------------------------------------
ModuleNotFoundError Traceback (most recent call last)
<ipython-input-17-90dc4368c687> in <module>
----> 1 from klefki.curves.barreto_naehrig import bn128
2 from klefki.algebra.utils import randfield
3 from operator import add
4 from functools import reduce
5
ModuleNotFoundError: No module named 'klefki.curves.barreto_naehrig'
[ ]:
class PGHR13:
def __init__(self, F, G):
"""
Setup toxic: t, k_a, k_b and k_c
"""
self.G = G
self.F = F
self.k_a = randfield(F)
self.k_b = randfield(F)
self.k_c = randfield(F)
@property
def toxic(self):
return (self.t, self.k_a, self.k_b, self.k_c)
def setup(self, A, B, C, H, Z):
self.pi_a = reduce(add, [self.G@a for a in A])
self.pi_a_ = self.pi_a @ self.k_a
self.pi_b = reduce(add, [self.G@b for b in B])
self.pi_b_ = self.pi_b @ self.k_b
self.pi_c = reduce(add, [self.G@c for c in C])
self.pi_c_ = self.pi_c @ self.k_c
self.pi_h = self.G @ H
self.pi_z = self.G @ Z
@property
def pi(self):
return (self.pi_a, self.pi_b, self.pi_c)
def check(self):
return G.e(self.pi_a, self.pi_b) / G.e(self.pi_c, self.G) == G.e(self.pi_h, self.pi_z)
[ ]:
[ ]:
[ ]: