def __init__(self, nCopies, nInputs, in0vv, in1vv, typvv, muxvv=None):
        self.nCopies = nCopies
        self.nCopyBits = util.clog2(nCopies)
        self.nInputs = nInputs
        self.nInBits = util.clog2(nInputs)
        self.prover = None
        self.in0vv = in0vv
        self.in1vv = in1vv
        self.typvv = typvv
        self.muxvv = muxvv
        self.muxbits = None
        self.inputs = []
        self.outputs = []

        fArith = FArith()
        self.in_a = fArith.new_cat("v_in")
        self.out_a = fArith.new_cat("v_out")
        self.sc_a = fArith.new_cat("v_sc")
        self.tV_a = fArith.new_cat("v_tv")
        self.nlay_a = fArith.new_cat("v_nlay")

        # nOutBits and nInBits for each layer
        self.layOutBits = [
            util.clog2(len(lay)) for lay in reversed(self.in0vv)
        ]
        self.layInBits = self.layOutBits[1:] + [self.nInBits]
    def __init__(self, nCopies, nInputs, in0vv, in1vv, typevv, muxvv=None):
        self.nCopies = nCopies
        self.nCopyBits = util.clog2(nCopies)
        self.nInBits = util.clog2(nInputs)
        self.ckt_inputs = []
        self.ckt_outputs = []
        self.muxbits = []
        self.layerNum = 0
        self.roundNum = 0

        assert len(in0vv) == len(in1vv)
        assert len(in0vv) == len(typevv)
        assert muxvv is None or len(in0vv) == len(muxvv)
        if muxvv is None:
            muxvv = [None] * len(in0vv)

        # build circuit and provers layer-by-layer
        self.layers = [InputLayer(self.nInBits)]
        self.arith_circuit = ArithCircuitBuilder(nCopies, nInputs, in0vv,
                                                 in1vv, typevv, muxvv)
        self.arith_circuit.set_muxbits(self.muxbits)

        for (lay, (in0v, in1v, muxv,
                   typev)) in enumerate(zip(in0vv, in1vv, muxvv, typevv)):
            # layer prover
            self.layers.append(
                LayerProver(self.layers[lay], self, in0v, in1v, typev, muxv))
Exemple #3
0
def run_giraffe(verifier_info):
    # pylint doesn't seed to understand how classmethods are inherited from metclasses
    from_pws = cver.CircuitVerifier.from_pws  # pylint: disable=no-member

    (input_layer, ver) = from_pws(pypws.parse_pws(verifier_info.pwsFile),
                                  verifier_info.nCopies)
    ver.build_prover()

    inputs = get_inputs(verifier_info, input_layer)
    ver.run(inputs)

    nInBits = util.clog2(len(input_layer))
    nCopies = VerifierInfo.nCopies
    nLayers = len(ver.in0vv)
    print "nInBits: %d, nCopies: %d, nLayers: %d" % (nInBits, nCopies, nLayers)
    (tMul, tAdd, tSub) = (0, 0, 0)
    for fArith in [ver.in_a, ver.out_a, ver.sc_a, ver.tV_a, ver.nlay_a]:
        (mul, add, sub) = fArith.get_counts()
        tMul += mul
        tAdd += add
        tSub += sub
        print "    %s: %d mul, %d add, %d sub" % (fArith.cat, mul, add, sub)

    print "  TOTAL: %d mul, %d add, %d sub" % (tMul, tAdd, tSub)

    lcosts = ver.local_costs()
    print "  LOCAL: %d mul, %d add, %d sub" % (lcosts.get(
        'mul', 0), lcosts.get('add', 0), lcosts.get('sub', 0))
Exemple #4
0
    def __init__(self, prevL, circuit, in0v, in1v, typev, muxv=None):
        # pylint: disable=protected-access
        self.prevL = prevL
        self.circuit = circuit
        self.nOutBits = util.clog2(len(in0v))
        self.roundNum = 0

        self.compute_v = []
        self.inputs = []
        self.output = []
        self.z2_save = []

        if muxv is None:
            # fake it
            muxv = [0] * len(in0v)
        assert len(in0v) == len(in1v) and len(in0v) == len(muxv) and len(
            in0v) == len(typev)

        # h computation subckt
        self.compute_h = LayerComputeH(self)

        # beta computation subckt
        self.compute_beta = LayerComputeBeta(self.circuit.nCopyBits)

        # z1chi computation subckt
        # this just takes advantage of the code in LayerComputeBeta
        # that does the dynamic-programming computation
        self.compute_z1chi = LayerComputeBeta(self.nOutBits)

        # v circuits are per-input---we collapse inputs in first nCopyBits rounds
        for _ in range(0, 2**self.prevL.nOutBits):
            lcv_tmp = LayerComputeV(self.circuit.nCopyBits)
            # outputs are collapsed
            lcv_tmp.expand_outputs = lcv_tmp.multiple_passes = False
            self.compute_v.append(lcv_tmp)

        # after finishing the first nCopyBits rounds, we only need one ComputeV circuit,
        # and everything is now 2nd order, so we only need three eval points, not four
        self.compute_v_final = LayerComputeV(self.prevL.nOutBits)
        self.compute_v_final.set_other_factors([util.THIRD_EVAL_POINT])

        # pergate computation subckts for "early" rounds
        self.gates = []
        max_muxbit = 0
        for (out, (in0, in1, mx, tp)) in enumerate(zip(in0v, in1v, muxv,
                                                       typev)):
            assert issubclass(tp, gateprover._GateProver)
            self.gates.append(tp(True, in0, in1, out, self, mx))
            if mx > max_muxbit:
                max_muxbit = mx
        muxlen = max_muxbit + 1
        self.circuit.muxbits += [0] * (muxlen - len(self.circuit.muxbits))
Exemple #5
0
def rand_inputs(nInBits, nCopies, inLay=None):
    out = []

    if inLay is None:
        inLay = [None] * (2**nInBits)
    else:
        nInBits = util.clog2(len(inLay))
        inLay += [0] * (2**nInBits - len(inLay))

    for _ in range(0, nCopies):
        out.append(
            [Defs.gen_random() if elm is None else elm for elm in inLay])

    return out
    def run(self, inputs, muxbits=None):
        ############
        # 0. Setup #
        ############
        assert self.prover is not None

        # set inputs and outputs
        self.prover.set_inputs(inputs)
        self.inputs = []
        for ins in inputs:
            self.inputs.extend(ins + [0] * (2**self.nInBits - len(ins)))
        self.outputs = util.flatten(self.prover.ckt_outputs)

        # set muxbits
        self.muxbits = muxbits
        if muxbits is not None:
            self.prover.set_muxbits(muxbits)

        ###############################################
        # 1. Compute multilinear extension of outputs #
        ###############################################
        nOutBits = util.clog2(len(self.in0vv[-1]))
        assert util.clog2(len(self.outputs)) == nOutBits + self.nCopyBits

        # pad out to power-of-2 number of copies
        self.outputs += [0] * (2**(nOutBits + self.nCopyBits) -
                               len(self.outputs))

        # generate random point in (z1, z2) \in F^{nOutBits + nCopyBits}
        z1 = [Defs.gen_random() for _ in range(0, nOutBits)]
        z2 = [Defs.gen_random() for _ in range(0, self.nCopyBits)]
        self.prover.set_z(z1, z2)

        # eval mlext of output at (z1,z2)
        output_mlext = VerifierIOMLExt(z1 + z2, self.out_a)
        expectNext = output_mlext.compute(self.outputs)

        ##########################################
        # 2. Interact with prover for each layer #
        ##########################################
        for lay in range(0, len(self.in0vv)):
            nInBits = self.layInBits[lay]
            nOutBits = self.layOutBits[lay]

            # random coins for this round
            w3 = [Defs.gen_random() for _ in range(0, self.nCopyBits)]
            w1 = [Defs.gen_random() for _ in range(0, nInBits)]
            w2 = [Defs.gen_random() for _ in range(0, nInBits)]

            # convenience
            ws = w3 + w1 + w2

            ###################
            ### A. Sumcheck ###
            ###################
            for rd in range(0, 2 * nInBits + self.nCopyBits):
                # get output from prv and check against expected value
                outs = self.prover.get_outputs()
                gotVal = (outs[0] + sum(outs)) % Defs.prime
                self.sc_a.did_add(len(outs))

                assert expectNext == gotVal, "Verification failed in round %d of layer %d" % (
                    rd, lay)

                # go to next round
                self.prover.next_round(ws[rd])
                expectNext = util.horner_eval(outs, ws[rd], self.sc_a)

            outs = self.prover.get_outputs()
            v1 = outs[0] % Defs.prime
            v2 = sum(outs) % Defs.prime
            self.tV_a.did_add(len(outs) - 1)

            ############################################
            ### B. Evaluate mlext of wiring predicates #
            ############################################
            tV_eval = self.eval_mlext(lay, z1, z2, w1, w2, w3, v1, v2)

            # check that we got the correct value from the last round of the sumcheck
            assert expectNext == tV_eval, "Verification failed computing tV for layer %d" % lay

            ###############################
            ### C. Extend to next layer ###
            ###############################
            tau = Defs.gen_random()
            if lay < len(self.in0vv) - 1:
                self.prover.next_layer(tau)
            expectNext = util.horner_eval(outs, tau, self.nlay_a)

            # next z values
            # z1 = w1 + ( w2 - w1 ) * tau; z2 is just w3
            z1 = [(elm1 + (elm2 - elm1) * tau) % Defs.prime
                  for (elm1, elm2) in zip(w1, w2)]
            self.nlay_a.did_sub(len(w1))
            self.nlay_a.did_mul(len(w1))
            self.nlay_a.did_add(len(w1))
            z2 = w3

        ##############################################
        # 3. Compute multilinear extension of inputs #
        ##############################################
        # Finally, evaluate mlext of input at z1, z2
        assert util.clog2(len(self.inputs)) == self.nInBits + self.nCopyBits
        self.inputs += [0] * (2**(self.nInBits + self.nCopyBits) -
                              len(self.inputs))
        input_mlext = VerifierIOMLExt(z1 + z2, self.in_a)
        input_mlext_eval = input_mlext.compute(self.inputs)

        assert input_mlext_eval == expectNext, "Verification failed checking input mlext"
 def __init__(self, nCopies):
     self.nCopies = nCopies
     self.nCopyBits = util.clog2(nCopies)
     self.muxbits = []