def evaluate_lagrange_polynomials(self, bits: int, t: FQ) -> "Dict": m = 1 << bits tm = t**m # print("m : " , m ) # print("t : " , t ) # print("t^m : ", tm) u = dict() for i in range(m): u.update({i: 0}) self._set_roots(bits) omega = self.w[bits] #TODO : if tm == 1 z = tm - FR(1) # print("z : ", z) l = z / FR(m) # print("l : ", l) for i in range(m): u[i] = l / (t - self.roots[bits][i]) l = l * omega return u
def __init__(self): # print("hello!") self.s = 1 self.t = field_modulus - self.s # TO find multiplicative subgroup root of unity lower than fqVal # s : group size(order) # t : root of unity while self.t % 2 != 1: self.s = self.s + 1 self.t = self.t >> 1 rem = self.t s = self.s - 1 # print("rem : ", rem) # print("s : ", s) self.w = {s: FR(5)**rem} self.wi = {s: FR(1) / self.w[s]} n = s - 1 while n >= 0: self.w.update({n: self.w[n + 1]**2}) self.wi.update({n: self.wi[n + 1]**2}) n -= 1 self.roots = {} self._set_roots(15)
def calc_values_at_T(self): domain_bits = self.setup["vk_proof"]["domainBits"] toxic_t = self.setup["toxic"]["t"] z_t = self.PF.compute_vanishing_polynomial(domain_bits, toxic_t) u = self.PF.evaluate_lagrange_polynomials(domain_bits, toxic_t) n_vars = int(self.circuit["nVars"]) a_t = [FR(0)] * n_vars b_t = [FR(0)] * n_vars c_t = [FR(0)] * n_vars # print(self.setup["vk_proof"]["polsA"][0]) # print(self.setup["vk_proof"]["polsA"][1]) # print(self.setup["vk_proof"]["polsA"][2]) for s in range(n_vars): A = self.setup["vk_proof"]["polsA"][s] B = self.setup["vk_proof"]["polsB"][s] C = self.setup["vk_proof"]["polsC"][s] if A != None: for c in A: a_t[s] = a_t[s] + u[int(c)] * int(A[c]) if B != None: for c in B: b_t[s] = b_t[s] + u[int(c)] * int(B[c]) if C != None: for c in C: c_t[s] = c_t[s] + u[int(c)] * int(C[c]) return [a_t, b_t, c_t]
def calc_polynomials(self): num_constraints = len(self.circuit["constraints"]) # consts = self.circuit["constraints"] for c in range(num_constraints): A = self.circuit["constraints"][c][0] B = self.circuit["constraints"][c][1] C = self.circuit["constraints"][c][2] for s in A: self.setup["vk_proof"]["polsA"][int(s)] = { str(c): A[s] if A[s] != None else None } for s in B: self.setup["vk_proof"]["polsB"][int(s)] = { str(c): B[s] if B[s] != None else None } for s in C: self.setup["vk_proof"]["polsC"][int(s)] = { str(c): C[s] if C[s] != None else None } # to ensure soundness of input consistency # input_i * 0 = 0 n_pub_plus_n_out = int(self.circuit["nPubInputs"]) + int( self.circuit["nOutputs"]) for i in range(n_pub_plus_n_out + 1): self.setup["vk_proof"]["polsA"][i] = { str(num_constraints + i): FR(1) }
def calc_encrypted_values_at_T(self): num_vars = int(self.circuit["nVars"]) n_pub_plus_n_out = int(self.circuit["nPubInputs"]) + int( self.circuit["nOutputs"]) + 1 v = self.calc_values_at_T() A = [None] * num_vars B1 = [None] * num_vars B2 = [None] * num_vars C = [None] * num_vars IC = [None] * n_pub_plus_n_out kalfa = FR(5) #TODO : should turn into random kbeta = FR(5) #TODO : should turn into random kgamma = FR(5) #TODO : should turn into random kdelta = FR(5) #TODO : should turn into random inv_delta = 1 / kdelta inv_gamma = 1 / kgamma
def _set_roots(self, n: int): self.roots = {} for i in reversed(range(0, n + 1)): r = FR(1) nroots = 1 << i rootsi = {} for j in range(nroots): rootsi.update({j: r}) r = r * self.w[i] self.roots.update({i: rootsi})
def __init__(self, circuit_path): with open(circuit_path) as json_file: self.circuit = json.load(json_file) num_vars = int(self.circuit["nVars"]) self.setup = { "vk_proof": { "protocol": "groth", "nVars": int(self.circuit["nVars"]), "nPublic": int(self.circuit["nPubInputs"] + self.circuit["nOutputs"]), "domainBits": 0, "domainSize": 0, "polsA": [None] * num_vars, "polsB": [None] * num_vars, "polsC": [None] * num_vars }, "vk_verifier": { "protocol": "groth", "nPublic": int(self.circuit["nPubInputs"] + self.circuit["nOutputs"]) }, "toxic": {} } total_domain = int(self.circuit["nConstraints"]) + int( self.circuit["nPubInputs"]) + int(self.circuit["nOutputs"]) self.setup["vk_proof"]["domainBits"] = Polfield.log2(total_domain) + 1 self.setup["vk_proof"][ "domainSize"] = 1 << self.setup["vk_proof"]["domainBits"] #TODO : need random function self.setup["toxic"]["t"] = FR(5) self.PF = Polfield()
def compute_vanishing_polynomial(self, bits: int, t: FQ): # t : toxic waste(셋업 마치면 사라져야되는 값) # m : constraints 수에 근접(A, B, C 행렬의 row 갯수), 무조껀 짝수 # -> taget polynomial H * T = A*u + B*u - C*u m = 1 << bits return t**m - FR(1)