Пример #1
0
def run_one_test(nInBits, nCopies):
    nOutBits = nInBits

    (in0v, in1v, typv) = randutil.rand_ckt(nOutBits, nInBits)
    inputs = randutil.rand_inputs(nInBits, nCopies)

    circuit = CircuitProver(nCopies, 2**nInBits, [in0v], [in1v], [typv])
    circuit.set_inputs(inputs)

    z1 = [Defs.gen_random() for _ in xrange(0, nOutBits)]
    z2 = [Defs.gen_random() for _ in xrange(0, circuit.nCopyBits)]

    circuit.set_z(z1, z2, None, None, True)

    # mlExt of outputs
    outflat = util.flatten(circuit.ckt_outputs)
    inLayer_mults = LayerComputeBeta(nOutBits + circuit.nCopyBits, z1 + z2)
    assert len(outflat) == len(inLayer_mults.outputs)
    inLayermul = util.mul_vecs(inLayer_mults.outputs, outflat)
    inLayerExt = sum(inLayermul) % Defs.prime

    w1 = [Defs.gen_random() for _ in xrange(0, nInBits)]
    w2 = [Defs.gen_random() for _ in xrange(0, nInBits)]
    w3 = [Defs.gen_random() for _ in xrange(0, circuit.nCopyBits)]

    initOutputs = circuit.get_outputs()

    assert inLayerExt == (initOutputs[0] + sum(initOutputs)) % Defs.prime

    for i in xrange(0, len(w3)):
        circuit.next_round(w3[i])
        circuit.get_outputs()

    for i in xrange(0, len(w1)):
        circuit.next_round(w1[i])
        circuit.get_outputs()

    for i in xrange(0, len(w2)):
        circuit.next_round(w2[i])
        finalOutputs = circuit.get_outputs()

    # check the outputs by computing mlext of layer input directly

    inflat = util.flatten(inputs)

    v1_mults = LayerComputeBeta(circuit.layer_inbits[0] + circuit.nCopyBits,
                                w1 + w3)
    assert len(inflat) == len(v1_mults.outputs)
    v1inmul = util.mul_vecs(v1_mults.outputs, inflat)
    v1 = sum(v1inmul) % Defs.prime

    v2_mults = LayerComputeBeta(circuit.layer_inbits[0] + circuit.nCopyBits,
                                w2 + w3)
    assert len(inflat) == len(v2_mults.outputs)
    v2inmul = util.mul_vecs(v2_mults.outputs, inflat)
    v2 = sum(v2inmul) % Defs.prime

    assert v1 == finalOutputs[0]
    assert v2 == sum(finalOutputs) % Defs.prime
Пример #2
0
    def __init__(self, nInBits, circuit, in0v, in1v, typev, muxv=None):
        # pylint: disable=protected-access
        self.nInBits = nInBits
        self.circuit = circuit
        self.nOutBits = util.clog2(len(in0v))
        self.roundNum = 0

        self.muls = None
        self.compute_v = []
        self.inputs = []
        self.output = []

        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, circuit.comp_h)

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

        # z1chi computation subckt
        # this uses the Verifier's fast beta eval code
        self.compute_z1chi = None
        self.compute_z1chi_2 = None

        # v circuits are per-input---we collapse inputs in first nCopyBits rounds
        for _ in xrange(0, 2**self.nInBits):
            lcv_tmp = LayerComputeV(self.circuit.nCopyBits, circuit.comp_v)
            # 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.nInBits, circuit.comp_v_fin)
        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(izip(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
        assert len(self.circuit.muxbits
                   ) >= muxlen, "Expected %d muxbits, found %d" % (
                       muxlen, len(self.circuit.muxbits))
Пример #3
0
def speed_test(num_tests):
    nBits = random.randint(3, 8)
    inputs = [ [ Defs.gen_random() for _ in xrange(0, nBits)  ] for _ in xrange(0, num_tests) ]

    lcb = LayerComputeBeta(nBits)
    lcb.other_factors = []
    runtime = time.time()
    for idx in xrange(0, num_tests):
        lcb.set_inputs(inputs[idx])
    runtime = time.time() - runtime

    runtime2 = time.time()
    for idx in xrange(0, num_tests):
        VerifierIOMLExt.compute_beta(inputs[idx])
    runtime2 = time.time() - runtime2

    print "nBits: %d\nLayerComputeBeta: %f\nVerifierIOMLExt: %f\n" % (nBits, runtime, runtime2)
Пример #4
0
def run_one_test(nbits, squawk, nbins, pattern):
    z = [Defs.gen_random() for _ in xrange(0, nbits)]

    inv = [Defs.gen_random() for _ in xrange(0, (2**nbits) - nbins)]
    if pattern is 0:
        inv += [0 for _ in xrange(0, nbins)]
    elif pattern is 1:
        inv += [1 for _ in xrange(0, nbins)]
    elif pattern == 2:
        inv += [(i % 2) for i in xrange(0, nbins)]
    elif pattern == 3:
        inv += [((i + 1) % 2) for i in xrange(0, nbins)]
    else:
        inv += [random.randint(0, 1) for _ in xrange(0, nbins)]

    assert len(inv) == (2**nbits)

    Defs.track_fArith = True
    fa = Defs.fArith()
    oldrec = fa.new_cat("old")
    newrec = fa.new_cat("new")
    nw2rec = fa.new_cat("nw2")

    oldbeta = LayerComputeBeta(nbits, z, oldrec)
    oldval = sum(util.mul_vecs(oldbeta.outputs, inv)) % Defs.prime
    oldrec.did_mul(len(inv))
    oldrec.did_add(len(inv) - 1)

    newcomp = VerifierIOMLExt(z, newrec)
    newval = newcomp.compute(inv)

    nw2comp = LayerComputeV(nbits, nw2rec)
    nw2comp.other_factors = []
    nw2comp.set_inputs(inv)
    for zz in z:
        nw2comp.next_round(zz)
    nw2val = nw2comp.prevPassValue

    assert oldval == newval, "error for inputs (new) %s : %s" % (str(z),
                                                                 str(inv))
    assert oldval == nw2val, "error for inputs (nw2) %s : %s" % (str(z),
                                                                 str(inv))

    if squawk:
        print
        print "nbits: %d" % nbits
        print "OLD: %s" % str(oldrec)
        print "NEW: %s" % str(newrec)
        print "NW2: %s" % str(nw2rec)

    betacomp = VerifierIOMLExt.compute_beta(z)
    beta_lo = random.randint(0, 2**nbits - 1)
    beta_hi = random.randint(beta_lo, 2**nbits - 1)
    betacomp2 = VerifierIOMLExt.compute_beta(z, None, 1, beta_lo, beta_hi)
    # make sure that the right range was generated, and correctly
    assert len(betacomp) == len(betacomp2)
    assert all([b is None for b in betacomp2[:beta_lo]])
    assert all([b is not None for b in betacomp2[beta_lo:beta_hi + 1]])
    assert all([b is None for b in betacomp2[beta_hi + 1:]])
    assert all([
        b2 == b if b2 is not None else True
        for (b, b2) in zip(betacomp, betacomp2)
    ])

    return newrec.get_counts()
Пример #5
0
    import os.path
    import random
    import sys
    import time
except:
    assert False
else:
    sys.path.insert(1, os.path.abspath(os.path.join(sys.path[0], os.pardir)))

from libfennel import util
from libfennel.circuitverifier import VerifierIOMLExt
from libfennel.defs import Defs
from libfennel.layercompute import LayerComputeBeta

nOutBits = 4
lcv = LayerComputeBeta(nOutBits)

def run_test():
    # pylint: disable=global-variable-undefined,redefined-outer-name
    tinputs = [Defs.gen_random() for _ in xrange(0, nOutBits)]
    taus = [Defs.gen_random() for _ in xrange(0, nOutBits)]
    lcv.set_inputs(tinputs)
    assert lcv.outputs == VerifierIOMLExt.compute_beta(tinputs)

    inputs = [util.chi(util.numToBin(x, nOutBits), tinputs) for x in xrange(0, 2**nOutBits)]

    global scratch
    global outputs

    scratch = list(inputs)
    outputs = list(inputs)
Пример #6
0
class LayerProver(object):
    def __init__(self, nInBits, circuit, in0v, in1v, typev, muxv=None):
        # pylint: disable=protected-access
        self.nInBits = nInBits
        self.circuit = circuit
        self.nOutBits = util.clog2(len(in0v))
        self.roundNum = 0

        self.muls = None
        self.compute_v = []
        self.inputs = []
        self.output = []

        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, circuit.comp_h)

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

        # z1chi computation subckt
        # this uses the Verifier's fast beta eval code
        self.compute_z1chi = None
        self.compute_z1chi_2 = None

        # v circuits are per-input---we collapse inputs in first nCopyBits rounds
        for _ in xrange(0, 2**self.nInBits):
            lcv_tmp = LayerComputeV(self.circuit.nCopyBits, circuit.comp_v)
            # 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.nInBits, circuit.comp_v_fin)
        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(izip(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
        assert len(self.circuit.muxbits
                   ) >= muxlen, "Expected %d muxbits, found %d" % (
                       muxlen, len(self.circuit.muxbits))

    # set new inputs
    def set_inputs(self, inputs):
        assert len(
            inputs) == self.circuit.nCopies, "Got inputs for the wrong #copies"
        self.inputs = inputs
        for inX in xrange(0, 2**self.nInBits):
            # transpose input matrix
            inXVals = [inCopy[inX] for inCopy in inputs]
            self.compute_v[inX].set_inputs(inXVals)

    # set a new z vector
    def set_z(self, z1, z2, z1_2, muls, project_line):
        self.roundNum = 0
        self.compute_beta.set_inputs(z2)
        if z1_2 is not None:
            self.compute_z1chi = VerifierIOMLExt.compute_beta(
                z1, self.circuit.comp_chi, muls[0])
            self.compute_z1chi_2 = VerifierIOMLExt.compute_beta(
                z1_2, self.circuit.comp_chi, muls[1])
            assert len(
                muls
            ) == 2, "Got muls of wrong size with non-None z1_2 in set_z()"
        else:
            self.compute_z1chi = VerifierIOMLExt.compute_beta(
                z1, self.circuit.comp_chi)
            self.compute_z1chi_2 = None
            assert muls is None

        # are we going to project a line at the beginning of the next round?
        self.compute_h.project_line = project_line

        # loop over all the gates and make them update their z coeffs
        for g in self.gates:
            g.set_z()

    # compute fj[0], fj[1], fj[-1], and maybe fj[2]
    def compute_outputs(self):
        # if we're at the last round, just return h coefficients
        if self.roundNum == self.circuit.nCopyBits + 2 * self.nInBits:
            self.output = self.compute_h.output
            return

        inEarlyRounds = True
        if self.roundNum >= self.circuit.nCopyBits:
            inEarlyRounds = False

        if inEarlyRounds:
            # go through each copy of the circuit
            out = [0, 0, 0, 0]
            for copy in xrange(0, len(self.compute_beta.outputs), 2):
                vals = [0, 0, 0, 0]
                # go through each gate, summing contribution from this copy
                for g in self.gates:
                    g.compute_outputs(copy)
                    for j in xrange(0, 4):
                        vals[j] += g.output[j]
                        vals[j] %= Defs.prime

                vals[0] *= self.compute_beta.outputs[copy]
                vals[0] %= Defs.prime
                out[0] += vals[0]
                out[0] %= Defs.prime

                vals[1] *= self.compute_beta.outputs[copy + 1]
                vals[1] %= Defs.prime
                out[1] += vals[1]
                out[1] %= Defs.prime

                # index with [copy >> 1] because expand_outputs is false in compute_beta
                vals[2] *= self.compute_beta.outputs_fact[0][copy >> 1]
                vals[2] %= Defs.prime
                out[2] += vals[2]
                out[2] %= Defs.prime

                vals[3] *= self.compute_beta.outputs_fact[1][copy >> 1]
                vals[3] %= Defs.prime
                out[3] += vals[3]
                out[3] %= Defs.prime

                if self.circuit.comp_out:
                    self.circuit.comp_out.did_add(4 * len(self.gates) + 4)
                    self.circuit.comp_out.did_mul(4)

            self.output = util.interpolate_cubic(out, self.circuit.comp_out)

        else:
            # late rounds: only one set of gates over which to sum;
            # in these rounds we are updating w1 and then w2
            out = [0, 0, 0]
            for g in self.gates:
                g.compute_outputs()
                # sum contributions from this gate
                for j in xrange(0, 3):
                    out[j] += g.output[j]
                    out[j] %= Defs.prime

            for j in xrange(0, 3):
                out[j] *= self.compute_beta.prevPassValue

            if self.circuit.comp_out:
                self.circuit.comp_out.did_add(3 * len(self.gates))
                self.circuit.comp_out.did_mul(3)

            self.output = util.interpolate_quadratic(out,
                                                     self.circuit.comp_out)

    # do updates upon receiving new random value
    def next_round(self, val):
        assert self.roundNum < self.circuit.nCopyBits + 2 * self.nInBits

        inLateRounds = True
        # do beta and V updates
        if self.roundNum < self.circuit.nCopyBits:
            inLateRounds = False
            self.compute_beta.next_round(val)
            for cv in self.compute_v:
                cv.next_round(val)
            # no gate updates in early rounds: gate circuits don't update state

        # gotta do some juggling now that we're done with the w3 updates
        if self.roundNum == self.circuit.nCopyBits - 1:
            # set up compute_v_final with prevPassValues from the per-input compute_v instances
            inputs = [cv.prevPassValue for cv in self.compute_v]
            assert all(elm is not None for elm in inputs)
            self.compute_v_final.set_inputs(inputs)

            # prepare gates for final rounds
            for g in self.gates:
                g.set_early(False)
                g.set_z()

        # updating w1 or w2, which requires updating compute_v_final and the gates
        if inLateRounds:
            self.compute_v_final.next_round(val)
            for g in self.gates:
                g.next_round(val)

        # finally, update the h_vals (needs to be done after compute_v and compute_beta are updated)
        self.compute_h.next_round(val)

        self.roundNum += 1
Пример #7
0
def run_one_test(nInBits, nCopies):
    nOutBits = nInBits

    circuit = _DummyCircuitProver(nCopies)

    (in0v, in1v, typv) = randutil.rand_ckt(nOutBits, nInBits)
    typc = [tc.cgate for tc in typv]
    inputs = randutil.rand_inputs(nInBits, nCopies)

    # compute outputs
    ckt = ArithCircuit()
    inCktLayer = ArithCircuitInputLayer(ckt, nOutBits)
    outCktLayer = ArithCircuitLayer(ckt, inCktLayer, in0v, in1v, typc)
    ckt.layers = [inCktLayer, outCktLayer]
    outputs = []
    for inp in inputs:
        ckt.run(inp)
        outputs.append(ckt.outputs)

    z1 = [Defs.gen_random() for _ in xrange(0, nOutBits)]
    z2 = [Defs.gen_random() for _ in xrange(0, circuit.nCopyBits)]

    outLayer = LayerProver(nInBits, circuit, in0v, in1v, typv)
    outLayer.set_inputs(inputs)
    outLayer.set_z(z1, z2, None, None, True)

    # mlExt of outputs
    outflat = util.flatten(outputs)
    inLayer_mults = LayerComputeBeta(nOutBits + outLayer.circuit.nCopyBits,
                                     z1 + z2)
    assert len(outflat) == len(inLayer_mults.outputs)
    inLayermul = util.mul_vecs(inLayer_mults.outputs, outflat)
    inLayerExt = sum(inLayermul) % Defs.prime

    w3 = [Defs.gen_random() for _ in xrange(0, circuit.nCopyBits)]
    w1 = [Defs.gen_random() for _ in xrange(0, nInBits)]
    w2 = [Defs.gen_random() for _ in xrange(0, nInBits)]

    outLayer.compute_outputs()
    initOutputs = outLayer.output

    assert inLayerExt == (initOutputs[0] + sum(initOutputs)) % Defs.prime

    for i in xrange(0, len(w3)):
        outLayer.next_round(w3[i])
        outLayer.compute_outputs()

    for i in xrange(0, len(w1)):
        outLayer.next_round(w1[i])
        outLayer.compute_outputs()

    for i in xrange(0, len(w2)):
        outLayer.next_round(w2[i])
        outLayer.compute_outputs()

    finalOutputs = outLayer.output

    # check the outputs by computing mlext of layer input directly

    inflat = util.flatten(inputs)

    v1_mults = LayerComputeBeta(outLayer.nInBits + outLayer.circuit.nCopyBits,
                                w1 + w3)
    assert len(inflat) == len(v1_mults.outputs)
    v1inmul = util.mul_vecs(v1_mults.outputs, inflat)
    v1 = sum(v1inmul) % Defs.prime

    v2_mults = LayerComputeBeta(outLayer.nInBits + outLayer.circuit.nCopyBits,
                                w2 + w3)
    assert len(inflat) == len(v2_mults.outputs)
    v2inmul = util.mul_vecs(v2_mults.outputs, inflat)
    v2 = sum(v2inmul) % Defs.prime

    assert v1 == finalOutputs[0]
    assert v2 == sum(finalOutputs) % Defs.prime