def compute_outputs_late(self): assert self.roundNum < 2 * self.layer.prevL.nOutBits # evaluate gatefn at third point (-1) if self.roundNum < self.layer.prevL.nOutBits: isOneVal = util.bit_is_set(self.in0, self.roundNum) leftVal = self.layer.compute_v_final.outputs_fact[0][self.in0] valForTwo = self.gatefn(leftVal, self.accum_in1) else: isOneVal = util.bit_is_set(self.in1, self.roundNum - self.layer.prevL.nOutBits) rightVal = self.layer.compute_v_final.outputs_fact[0][self.in1] valForTwo = self.gatefn(self.accum_in0, rightVal) # evaluate addmul at third point valForTwo *= util.third_eval_point(self.accum_z1, isOneVal) valForTwo %= Defs.prime # produce outputs for 0, 1, 2 out = [0, 0, valForTwo] valForZeroOne = self.accum_z1 * self.gatefn(self.accum_in0, self.accum_in1) valForZeroOne %= Defs.prime if isOneVal: out[1] = valForZeroOne else: out[0] = valForZeroOne self.output = out
def compute_nosavebits(self, inputs): assert len(inputs) <= 2**len( self.z_vals) and len(inputs) > 2**(len(self.z_vals) - 1) inputs = inputs + [0] * ((2**len(self.z_vals)) - len(inputs)) intermeds = [None] * len(self.z_vals) total_adds = 0 total_muls = 0 retval = None for (idx, val) in enumerate(inputs): for i in range(0, len(intermeds)): if util.bit_is_set(idx, i): chi = self.z_vals[i] else: chi = self.mzp1_vals[i] val *= chi val %= Defs.prime total_muls += 1 if intermeds[i] is None: intermeds[i] = val break else: val = (val + intermeds[i]) % Defs.prime total_adds += 1 intermeds[i] = None if i == len(intermeds) - 1: retval = val if self.rec is not None: self.rec.did_add(total_adds) self.rec.did_mul(total_muls) return retval
def next_round(self, val): # early rounds: no gate-internal state if self.isEarly: return if self.roundNum >= 2 * self.layer.prevL.nOutBits: # no changes after the first 2 * g' rounds return # figure out how to update GateProver's state this round isOneVal = False if self.roundNum < self.layer.prevL.nOutBits: ### updating omega_1 value # first, figure out how to update wiring predicate isOneVal = util.bit_is_set(self.in0, self.roundNum) # second, update appropriate V value if self.roundNum < self.layer.prevL.nOutBits - 1: self.accum_in0 = self.layer.compute_v_final.outputs[self.in0] else: self.accum_in0 = self.layer.compute_v_final.prevPassValue else: ### updating omega_2 value # first, figure out how to update wiring predicate isOneVal = util.bit_is_set(self.in1, self.roundNum - self.layer.prevL.nOutBits) # second, update appropriate V value if self.roundNum < 2 * self.layer.prevL.nOutBits - 1: self.accum_in1 = self.layer.compute_v_final.outputs[self.in1] else: self.accum_in1 = self.layer.compute_v_final.prevPassValue self.accum_z1 *= val if isOneVal else (1 - val) self.accum_z1 %= Defs.prime self.roundNum += 1
def compute_savebits(self, inputs): assert len(inputs) <= 2**len( self.z_vals) and len(inputs) > 2**(len(self.z_vals) - 1) inputs = inputs + [0] * ((2**len(self.z_vals)) - len(inputs)) intermeds = [None] * len(self.z_vals) total_adds = 0 total_muls = 0 retval = None for (idx, val) in enumerate(inputs): if val is 0: val = (0, None) elif val is 1: val = (1, None) else: val = (None, val) for i in range(0, len(intermeds)): if util.bit_is_set(idx, i): chi = self.z_vals[i] else: chi = self.mzp1_vals[i] if val[0] is 0: pass elif val[0] is 1: val = (1, chi) else: val = (None, (val[1] * chi) % Defs.prime) total_muls += 1 if intermeds[i] is None: intermeds[i] = val break else: val2 = intermeds[i] intermeds[i] = None if val[0] is 1: if val2[0] is 1: nval = (1, None) elif val2[0] is 0: nval = (None, val[1]) else: nval = (None, (val[1] + val2[1]) % Defs.prime) total_adds += 1 elif val[0] is 0: if val2[0] is 0: nval = (0, None) else: nval = (None, val2[1]) else: if val2[0] is 0: nval = val else: nval = (None, (val[1] + val2[1]) % Defs.prime) total_adds += 1 val = nval if i == len(intermeds) - 1: retval = val[1] if self.rec is not None: self.rec.did_add(total_adds) self.rec.did_mul(total_muls) return retval