def __init__(self, circuit, a, b): self.a = a self.b = b self.c = circuit.create_var() circuit.constrain({self.a: FieldP(1)}, {self.b: FieldP(1)}, {self.c: FieldP(1)}) super().__init__(circuit, {a, b})
def __add__(self, p): cnt = max(len(self.coefs), len(p.coefs)) coefs = [FieldP(0)] * cnt for i in range(cnt): coefs[i] += self.coefs[i] if len(self.coefs) > i else FieldP(0) coefs[i] += p.coefs[i] if len(p.coefs) > i else FieldP(0) return PolynomialP(coefs)
def singleton(at, height, length): p = PolynomialP([FieldP(1)]) for i in range(1, length + 1): if i != at: p *= PolynomialP([FieldP(-i), FieldP(1)]) p *= height / p.evaluate(FieldP(at)) return p
def _check(self): # Check if all variables are assigned for v in self.vars: if not v.is_assigned(): raise Exception("Not all variables are assigned!") # Check if all values satisfy the gates for g in self.gates: L = sum([v.value * coef for v, coef in g.l.items()], FieldP(0)) R = sum([v.value * coef for v, coef in g.r.items()], FieldP(0)) O = sum([v.value * coef for v, coef in g.o.items()], FieldP(0)) res = L * R - O if res != FieldP(0): raise Exception("Gates not satisfied!")
def __init__(self, circuit, a): self.a = a curr = self.a for r in range(4): curr2 = Mul(circuit, curr, curr).output() curr3 = Mul(circuit, curr2, curr).output() curr = Add(circuit, curr3, circuit.create_var(FieldP(r))).output() self.o = curr super().__init__(circuit, {self.a,})
def __truediv__(self, p): num = self.normalized().coefs den = p.normalized().coefs if len(num) >= len(den): shiftlen = len(num) - len(den) den = [FieldP(0)] * shiftlen + den else: return PolynomialP(num).normalized() quot = [] divisor = den[-1] for _ in range(shiftlen + 1): mult = num[-1] / divisor quot = [mult] + quot if mult != FieldP(0): d = [mult * u for u in den] num = [u - v for u, v in zip(num, d)] num.pop() den.pop(0) return PolynomialP(quot).normalized()
def __mul__(self, p): if type(p) is Vector: return PolynomialP([p * v for p, v in zip(self.coefs, p.vals)]) if type(p) is FieldP: return PolynomialP([c * p for c in self.coefs]) cnt = len(self.coefs) + len(p.coefs) - 1 coefs = [FieldP(0)] * cnt for i, coef1 in enumerate(self.coefs): for j, coef2 in enumerate(p.coefs): coefs[i + j] += coef1 * coef2 return PolynomialP(coefs)
def compile(self): syms = {sym: i for i, sym in enumerate(self.vars)} LRO = [[[FieldP(0)] * len(syms) for i in range(len(self.gates))] for i in range(3)] for i, gate in enumerate(self.gates): for k, v in gate.l.items(): LRO[0][i][syms[k]] = v LRO[0][i] = Vector(LRO[0][i]) for k, v in gate.r.items(): LRO[1][i][syms[k]] = v LRO[1][i] = Vector(LRO[1][i]) for k, v in gate.o.items(): LRO[2][i][syms[k]] = v LRO[2][i] = Vector(LRO[2][i]) return R1CSCircuit(list(self.inputs.keys()), LRO[0], LRO[1], LRO[2])
class GT: GENERATOR = FieldP(5) def __init__(self, val=None): self.value = val if val else GT.GENERATOR def __add__(self, other): ret = GT(self.value) ret.value += other.value return ret def __mul__(self, other): ret = GT(self.value) ret.value *= other return ret def __eq__(self, other): return type(self) == type(other) and self.value == other.value def __str__(self): return "GT({})".format(self.value) def __repr__(self): return str(self)
def evaluate(self): v = self.a.value for r in range(4): v = v * v * v + FieldP(r) self.o.assign(v)
def dot(self, v): from pairing import G1 from fieldp import FieldP return sum(tuple(v1 * v2 for v1, v2 in zip(self.vals, v.vals)), G1(FieldP(0)))
def __init__(self): self.vars = [] self.inputs = {} self.gates = [] self.one = self.create_var(FieldP(1)) self.create_input(self.one, '1')
def __init__(self, coefs): self.coefs = coefs if coefs else [FieldP(0)]
def normalized(self): coefs = list(self.coefs) while coefs and coefs[-1] == FieldP(0): coefs.pop() return PolynomialP(coefs)
def evaluate(self, x): sm = FieldP(0) for i, coef in enumerate(self.coefs): sm += coef * x.pow(i) return sm
def z(length): p = PolynomialP([FieldP(1)]) for i in range(1, length + 1): p *= PolynomialP([FieldP(-i), FieldP(1)]) return p
def __init__(self, qap): self.qap = qap num_publics = len(qap.inputs) # Toxic waste r_l = FieldP(123) r_r = FieldP(234) alphal = FieldP(345) alphar = FieldP(456) alphao = FieldP(789) beta = FieldP(8910) gamma = FieldP(910111) tau = FieldP(101112) g = G1() g_l = G1() * r_l g_r = G1() * r_r g_o = G1() * (r_l * r_r) # Proving key pk = ProvingKey( gl_Ltau=Vector( [g_l * p.evaluate(tau) for p in self.qap.L[num_publics:]]), gr_Rtau=Vector( [g_r * p.evaluate(tau) for p in self.qap.R[num_publics:]]), go_Otau=Vector( [g_o * p.evaluate(tau) for p in self.qap.O[num_publics:]]), gl_alphalLtau=Vector([ g_l * (alphal * p.evaluate(tau)) for p in self.qap.L[num_publics:] ]), gr_alpharRtau=Vector([ g_r * (alphar * p.evaluate(tau)) for p in self.qap.R[num_publics:] ]), go_alphaoOtau=Vector([ g_o * (alphao * p.evaluate(tau)) for p in self.qap.O[num_publics:] ]), g_taus=Vector([g * tau.pow(i) for i in range(100)]), glro_betaLROtau=Vector([ g_l * (beta * l.evaluate(tau)) + g_r * (beta * r.evaluate(tau)) + g_o * (beta * o.evaluate(tau)) for l, r, o in zip(self.qap.L[num_publics:], self.qap. R[num_publics:], self.qap.O[num_publics:]) ])) # Verification key vk = VerificationKey( g=g, g_alphal=g * alphal, g_alphar=g * alphar, g_alphao=g * alphao, g_gamma=g * gamma, g_betagamma=g * (beta * gamma), gl_Ltau=Vector( [g_l * p.evaluate(tau) for p in self.qap.L[:num_publics]]), gr_Rtau=Vector( [g_r * p.evaluate(tau) for p in self.qap.R[:num_publics]]), go_Otau=Vector( [g_o * p.evaluate(tau) for p in self.qap.O[:num_publics]]), go_Ztau=g_o * self.qap.Z.evaluate(tau)) self.pk = pk self.vk = vk
ret = GT(self.value) ret.value += other.value return ret def __mul__(self, other): ret = GT(self.value) ret.value *= other return ret def __eq__(self, other): return type(self) == type(other) and self.value == other.value def __str__(self): return "GT({})".format(self.value) def __repr__(self): return str(self) def e(a, b): ret = GT() ret *= a.value * b.value return ret if __name__ == '__main__': g1 = G1() * FieldP(4) g2 = G2() * FieldP(8) print(e(g1, g2))
def interpolate(vals): p = PolynomialP([FieldP(0)]) l = len(vals) for i, v in enumerate(vals): p += PolynomialP.singleton(i + 1, v, l) return p
lin_check = e(aLt, self.vk.g) == e(Lt, self.vk.g_alphal) and \ e(aRt, self.vk.g) == e(Rt, self.vk.g_alphar) and \ e(aOt, self.vk.g) == e(Ot, self.vk.g_alphao) coef_check = e(bLROt, self.vk.g_gamma) == e(Lt + Rt + Ot, self.vk.g_betagamma) return div_check and lin_check and coef_check if __name__ == '__main__': c = CircuitGenerator() leaves = [c.create_var() for _ in range(4)] root = MerkleTree(c, leaves).output() leaves[0].assign(FieldP(4)) leaves[1].assign(FieldP(9)) leaves[2].assign(FieldP(2)) leaves[3].assign(FieldP(23)) print("Converting the problem to R1CS form...") r1cs = c.compile() print("Done! Variables: {} Constraints: {}".format(len(r1cs.L), len(r1cs.L[0]))) print("Converting the problem to QAP form...") qap = QAP(r1cs) print("Done!") print("Generating the Pinocchio parameters...") pino = Pinocchio(qap) print("Done!")