Beispiel #1
0
def vanishing_poly(S):
    """
    args: 
       S   (m vector)
    returns:
       p(X) = (X-S1)*(X-S2)*...*(X-Sm)
    """
    p = Poly([Fp(1)])
    for s in S:
        p *= Poly([-s, Fp(1)])
    return p
Beispiel #2
0
def babysnark_prover(U, n_stmt, CRS, precomp, a):
    (m, n) = U.shape
    assert n == len(a)
    assert len(CRS) == (m + 1) + 2 + (n - n_stmt)
    assert len(ROOTS) >= m

    # Parse the CRS
    taus = CRS[:m + 1]
    bUis = CRS[-(n - n_stmt):]

    Uis, T = precomp

    # Target is the vanishing polynomial
    t = vanishing_poly(ROOTS[:m])

    # 1. Find the polynomial p(X)

    # Convert the basis polynomials Us to coefficient form by interpolating
    Us = [Poly.interpolate(ROOTS[:m], U[:, k]) for k in range(n)]

    # First compute v
    v = Poly([])
    for k in range(n):
        v += Us[k] * a[k]

    # Finally p
    p = v * v - 1

    # 2. Compute the H term
    # Find the polynomial h by dividing p / t
    h = p / t
    # assert p == h * t

    H = evaluate_in_exponent(taus, h)

    # 3. Compute the Vw terms, using precomputed Uis
    Vw = sum([Uis[k] * a[k] for k in range(n_stmt, n)], G * 0)
    # assert G * vw(tau) == Vw

    # 4. Compute the Bw terms
    Bw = sum([bUis[k - n_stmt] * a[k] for k in range(n_stmt, n)], G * 0)
    # assert G * (beta * vw(tau)) == Bw

    # V = G * v(tau)
    # assert H.pair(T) * GT == V.pair(V)

    # print('H:', H)
    # print('Bw:', Bw)
    # print('Vw:', Vw)
    return H, Bw, Vw
Beispiel #3
0
def babysnark_setup(U, n_stmt):
    (m, n) = U.shape
    assert n_stmt < n

    # Generate roots for each gate
    global ROOTS
    if len(ROOTS) < m:
        ROOTS = tuple(range(m))

    # Generate polynomials u from columns of U
    Us = [Poly.interpolate(ROOTS[:m], U[:, k]) for k in range(n)]

    # Trapdoors
    global tau, beta, gamma
    tau = random_fp()
    beta = random_fp()
    gamma = random_fp()

    # CRS elements
    CRS = [G * (tau ** i) for i in range(m+1)] + \
          [G * gamma, G * (beta * gamma)] + \
          [G * (beta * Ui(tau)) for Ui in Us[n_stmt:]]

    # Precomputation
    # Note: This is not considered part of the trusted setup, since it
    # could be computed direcftly from the G * (tau **i) terms.

    # Compute the target poly term
    t = vanishing_poly(ROOTS[:m])
    T = G * t(tau)

    # Evaluate the Ui's corresponding to statement values
    Uis = [G * Ui(tau) for Ui in Us]
    precomp = Uis, T

    return CRS, precomp
def vanishing_poly(omega, n):
    # For the special case of evaluating at all n powers of omega,
    # the vanishing poly has a special form.
    #  t(X) = (X-1)(X-omega)....(X-omega^(n-1)) = X^n - 1
    return Poly([Fp(-1)] + [Fp(0)] * (n - 1) + [Fp(1)])
Beispiel #5
0
def test_two_round(crstype):
    numr1players = 6
    numr2players = 6
    numpolys = 3
    crslen = 5

    n = numr1players + numr2players + 1
    numplayers = n - 1
    sends, recvs = get_routing(n)
    bcfuncs = gen_blockchain_funcs(sends, recvs)
    loop = asyncio.get_event_loop()
    public = {}

    if crstype == "BabySNARK":
        #generate a random alpha, gamma for each party
        trapdoors1 = [[random_fp() for j in range(2)]
                      for i in range(numr1players + 1)]
        #generate a random beta for round 2 players
        trapdoors2 = [random_fp() for i in range(numr2players)]
        trapdoors = trapdoors1 + trapdoors2
        polys = [
            Poly([random_fp() for j in range(crslen)]) for i in range(numpolys)
        ]
        public['polys'] = polys
        crs = init_babysnark(trapdoors[0], crslen)
        TestPlayer1 = BabySNARKr1Player
        TestPlayer2 = BabySNARKr2Player
        bc = Blockchain(sends[0], recvs[0], beacon=beacon_babysnark)

    #A proof is unnecessary for the first block as trapdoors are public
    pi = None
    #set the original CRS
    sends[0](0, ["SET_NOWAIT", [pi, crs]])
    bctask = loop.create_task(bc.run())
    mysleep = loop.create_task(asyncio.sleep(.5))
    loop.run_until_complete(mysleep)

    options = [{'roles': ['contributor']} for i in range(numplayers)]
    players = [None] * numplayers
    r1players = [
        TestPlayer1(i, trapdoors[i], sends[i], recvs[i], bcfuncs[i],
                    options[i - 1]) for i in range(1, numr1players + 1)
    ]
    r2players = [
        TestPlayer2(i, trapdoors[i], sends[i], recvs[i], bcfuncs[i],
                    options[i - 1], public)
        for i in range(numr1players + 1, numplayers + 1)
    ]
    r1players[numr1players // 2].roles += ["validator"]
    r2players[numr2players // 2].roles += ["validator"]
    r2players[0].roles += ["roundstarter"]
    r1players[-1].roles += ["roundender"]
    r2players[-1].roles += ["roundender"]
    players = r1players + r2players
    for i in range(3, numplayers, 3):
        players[i].roles += ["checkpoint"]

    #send starting message to first player
    sends[0](1, ["INC", None, crs])
    playertasks = [loop.create_task(player.run()) for player in players]
    for task in [bctask] + playertasks:
        task.add_done_callback(print_exception_callback)
    loop.run_until_complete(playertasks[-1])
    get_block = bcfuncs[1][1]
    mytask = loop.create_task(get_block("ALL"))
    blocks = loop.run_until_complete(mytask)
    assert TestPlayer2.verify_chain(blocks, public)
    bctask.cancel()
Beispiel #6
0
def _polydemo():
    p1 = Poly([1, 2, 3, 4, 5])
Beispiel #7
0
def prover_algo(witness, CRS, Qs, p_i_poly, perm_precomp):
    print("Starting the Prover Algorithm")
    n = int(len(witness) / 3)
    assert n & n - 1 == 0, "n must be a power of 2"
    id_domain, perm_domain, k, Ss = perm_precomp

    # We need to convert between representations to multiply and divide more
    # efficiently. In round 3 we have to divide a polynomial of degree 4*n+6
    # Not sure if there is a big benefit in keeping the lower order
    # representations or if it makes sense to do everything in the highest
    # order 8*n right away...

    # polys represented with n points
    omega = omega_base ** (2 ** 32 // n)
    ROOTS = [omega ** i for i in range(n)]
    PolyEvalRep = polynomialsEvalRep(Fp, omega, n)
    witness = [Fp(i) for i in witness]
    witness_poly_a = PolyEvalRep(ROOTS, witness[:n])
    witness_poly_b = PolyEvalRep(ROOTS, witness[n:n*2])
    witness_poly_c = PolyEvalRep(ROOTS, witness[2*n:])
    vanishing_pol_coeff = vanishing_poly(omega, n)

    # polys represented with 2*n points
    omega2 = omega_base ** (2 ** 32 // (2 * n))
    PolyEvalRep2 = polynomialsEvalRep(Fp, omega2, 2 * n)
    vanishing_poly_ext = PolyEvalRep2.from_coeffs(vanishing_pol_coeff)
    witness_poly_a_ext = PolyEvalRep2.from_coeffs(witness_poly_a.to_coeffs())
    witness_poly_b_ext = PolyEvalRep2.from_coeffs(witness_poly_b.to_coeffs())
    witness_poly_c_ext = PolyEvalRep2.from_coeffs(witness_poly_c.to_coeffs())

    # polys represented with 8*n points
    omega3 = omega_base ** (2 ** 32 // (8 * n))
    PolyEvalRep3 = polynomialsEvalRep(Fp, omega3, 8 * n)
    roots3 = [omega3 ** i for i in range(8 * n)]
    S1, S2, S3 = Ss
    S1_ext3 = PolyEvalRep3.from_coeffs(S1.to_coeffs())
    S2_ext3 = PolyEvalRep3.from_coeffs(S2.to_coeffs())
    S3_ext3 = PolyEvalRep3.from_coeffs(S3.to_coeffs())
    p_i_poly_ext3 = PolyEvalRep3.from_coeffs(p_i_poly.to_coeffs())
    qs_ext3 = [PolyEvalRep3.from_coeffs(q.to_coeffs()) for q in Qs]
    q_L_ext3, q_R_ext3, q_M_ext3, q_O_ext3, q_C_ext3 = qs_ext3

    # Following the paper, we are using the Fiat Shamir Heuristic. We are
    # Simulating 5 rounds of communication with the verifier using a
    # random oracle for verifier answers
    print("Starting Round 1...")

    # Generate "random" blinding scalars
    rand_scalars = [random_fp_seeded("1234") for i in range(9)]

    # Generate polys with the random scalars as coefficients and convert to
    # evaluation representation. These are needed for zero knowledge to
    # obfuscate the witness.
    a_blind_poly_ext = Poly([rand_scalars[1], rand_scalars[0]])
    b_blind_poly_ext = Poly([rand_scalars[3], rand_scalars[2]])
    c_blind_poly_ext = Poly([rand_scalars[5], rand_scalars[4]])
    a_blind_poly_ext = PolyEvalRep2.from_coeffs(a_blind_poly_ext)
    b_blind_poly_ext = PolyEvalRep2.from_coeffs(b_blind_poly_ext)
    c_blind_poly_ext = PolyEvalRep2.from_coeffs(c_blind_poly_ext)

    # These polynomals have random evaluations at all points except ROOTS where
    # they evaluate to the witness
    a_poly_ext = a_blind_poly_ext * vanishing_poly_ext + witness_poly_a_ext
    b_poly_ext = b_blind_poly_ext * vanishing_poly_ext + witness_poly_b_ext
    c_poly_ext = c_blind_poly_ext * vanishing_poly_ext + witness_poly_c_ext

    # Evaluate the witness polynomials in the exponent using the CRS
    a_eval_exp = evaluate_in_exponent(CRS, a_poly_ext.to_coeffs())
    b_eval_exp = evaluate_in_exponent(CRS, b_poly_ext.to_coeffs())
    c_eval_exp = evaluate_in_exponent(CRS, c_poly_ext.to_coeffs())

    first_output = [a_eval_exp, b_eval_exp, c_eval_exp]
    print("Round 1 Finished with output: ", first_output)

    print("Starting Round 2...")
    # Compute permutation challenges from imaginary verifier
    beta = random_fp_seeded(str(first_output) + "0")
    gamma = random_fp_seeded(str(first_output) + "1")

    # Compute permutation polynomial. z_1 is the blinding summand needed for ZK
    z_1 = Poly([rand_scalars[8], rand_scalars[7], rand_scalars[6]])
    z_1 = PolyEvalRep2.from_coeffs(z_1)
    z_1 = z_1 * vanishing_poly_ext
    accumulator_poly_eval = [Fp(1)]
    accumulator_poly_eval += [accumulator_factor(n,
                                                 i,
                                                 witness, beta,
                                                 id_domain,
                                                 perm_domain,
                                                 gamma)
                              for i in range(n-1)]
    accumulator_poly = PolyEvalRep(ROOTS, accumulator_poly_eval)
    accumulator_poly = z_1 + PolyEvalRep2.from_coeffs(accumulator_poly.to_coeffs())

    second_output = evaluate_in_exponent(CRS, accumulator_poly.to_coeffs())
    print("Round 2 Finished with output: ", second_output)

    print("Starting Round 3...")
    alpha = random_fp_seeded(str(first_output) + str(second_output))

    accumulator_poly_ext3 = PolyEvalRep3.from_coeffs(accumulator_poly.to_coeffs())

    # The third summand of t has the accumulator poly evaluated at a shift
    accumulator_poly_shift_evaluations = eval_poly(accumulator_poly,
                                                   roots3,
                                                   ROOTS[1])
    accumulator_poly_ext3_shift = PolyEvalRep3(roots3,
                                               accumulator_poly_shift_evaluations)

    a_poly_ext3 = PolyEvalRep3.from_coeffs(a_poly_ext.to_coeffs())
    b_poly_ext3 = PolyEvalRep3.from_coeffs(b_poly_ext.to_coeffs())
    c_poly_ext3 = PolyEvalRep3.from_coeffs(c_poly_ext.to_coeffs())

    id_poly_1_ext3 = PolyEvalRep3.from_coeffs(Poly([gamma, beta]))
    id_poly_2_ext3 = PolyEvalRep3.from_coeffs(Poly([gamma, beta * k]))
    id_poly_3_ext3 = PolyEvalRep3.from_coeffs(Poly([gamma, beta * k**2]))

    gamma_poly = PolyEvalRep3.from_coeffs(Poly([gamma]))
    L_1 = PolyEvalRep(ROOTS, [Fp(1)] + [Fp(0) for i in range(len(ROOTS)-1)])

    # Compute quotient polynomial: we are dividing by the vanishing poly which
    # has zeros at n roots so we need to do division by swapping to a coset
    # first summand should have degree 3n+1, second and third should have
    # degree 4n + 5
    t = ((a_poly_ext3 * b_poly_ext3 * q_M_ext3) +
         (a_poly_ext3 * q_L_ext3) +
         (b_poly_ext3 * q_R_ext3) +
         (c_poly_ext3 * q_O_ext3) +
         q_C_ext3 + p_i_poly_ext3)

    t += ((a_poly_ext3 + id_poly_1_ext3) *
          (b_poly_ext3 + id_poly_2_ext3) *
          (c_poly_ext3 + id_poly_3_ext3) * accumulator_poly_ext3 * alpha)

    t -= ((a_poly_ext3 + S1_ext3 * beta + gamma_poly) *
          (b_poly_ext3 + S2_ext3 * beta + gamma_poly) *
          (c_poly_ext3 + S3_ext3 * beta + gamma_poly) *
          accumulator_poly_ext3_shift * alpha)

    t += ((accumulator_poly_ext3 - PolyEvalRep3.from_coeffs(Poly([Fp(1)]))) *
          PolyEvalRep3.from_coeffs(L_1.to_coeffs()) * alpha ** 2)

    t = PolyEvalRep3.divideWithCoset(t.to_coeffs(), vanishing_pol_coeff)

    t_coeff = t.coefficients

    # We split up the polynomial t in three polynomials so that:
    # t= t_lo + x^n*t_mid + t^2n*t_hi
    # I found that n has actually to be (n+2) to accomodate the CRS because
    # t can be of degree 4n+5
    t_lo = Poly(t_coeff[:n+2])
    t_mid = Poly(t_coeff[n+2:2*(n+2)])
    t_hi = Poly(t_coeff[2*(n+2):])

    t_lo_eval_exp = evaluate_in_exponent(CRS, t_lo)
    t_mid_eval_exp = evaluate_in_exponent(CRS, t_mid)
    t_hi_eval_exp = evaluate_in_exponent(CRS, t_hi)

    third_output = [t_lo_eval_exp, t_mid_eval_exp, t_hi_eval_exp]
    print("Round 3 Finished with output: ", third_output)

    print("Starting Round 4...")
    # Compute the evaluation challenge
    zeta = random_fp_seeded(str(first_output) +
                            str(second_output) +
                            str(third_output))

    # Compute the opening evaluations
    a_zeta = eval_poly(a_poly_ext, [zeta])[0]
    b_zeta = eval_poly(b_poly_ext, [zeta])[0]
    c_zeta = eval_poly(c_poly_ext, [zeta])[0]
    S_1_zeta = eval_poly(S1, [zeta])[0]
    S_2_zeta = eval_poly(S2, [zeta])[0]
    t_zeta = eval_poly(PolyEvalRep3.from_coeffs(t), [zeta])[0]
    accumulator_shift_zeta = eval_poly(accumulator_poly_ext3,
                                       [zeta * ROOTS[1]])[0]

    # Compute linerisation polynomial
    r = (q_M_ext3 * a_zeta * b_zeta +
         q_L_ext3 * a_zeta +
         q_R_ext3 * b_zeta +
         q_O_ext3 * c_zeta +
         q_C_ext3)
    r += (accumulator_poly_ext3 *
          (a_zeta + beta * zeta + gamma) *
          (b_zeta + beta * k * zeta + gamma) *
          (c_zeta + beta * (k ** 2) * zeta + gamma) * alpha)
    r -= (S3_ext3 *
          (a_zeta + beta * S_1_zeta + gamma) *
          (b_zeta + beta * S_2_zeta + gamma) *
          alpha * beta * accumulator_shift_zeta)
    r += accumulator_poly_ext3 * eval_poly(L_1, [zeta])[0] * alpha ** 2

    # Evaluate r at zeta
    r_zeta = eval_poly(r, [zeta])[0]

    fourth_output = [a_zeta, b_zeta, c_zeta, S_1_zeta, S_2_zeta,
                     accumulator_shift_zeta, t_zeta, r_zeta]
    print("Round 4 Finished with output: ", fourth_output)

    print("Starting Round 5...")
    # Compute opening challeng
    nu = random_fp_seeded(str(first_output) +
                          str(second_output) +
                          str(third_output) +
                          str(fourth_output))

    # Compute opening proof polynomial
    W_zeta = (PolyEvalRep3.from_coeffs(t_lo) +
              PolyEvalRep3.from_coeffs(t_mid) * zeta ** (n+2) +
              PolyEvalRep3.from_coeffs(t_hi) * zeta ** (2*(n+2)) -
              PolyEvalRep3.from_coeffs(Poly([t_zeta])) +
              (r - PolyEvalRep3.from_coeffs(Poly([r_zeta]))) * nu +
              (a_poly_ext3 - PolyEvalRep3.from_coeffs(Poly([a_zeta]))) * nu ** 2 +
              (b_poly_ext3 - PolyEvalRep3.from_coeffs(Poly([b_zeta]))) * nu ** 3 +
              (c_poly_ext3 - PolyEvalRep3.from_coeffs(Poly([c_zeta]))) * nu ** 4 +
              (S1_ext3 - PolyEvalRep3.from_coeffs(Poly([S_1_zeta]))) * nu ** 5 +
              (S2_ext3 - PolyEvalRep3.from_coeffs(Poly([S_2_zeta]))) * nu ** 6)
    W_zeta = W_zeta / PolyEvalRep3.from_coeffs(Poly([-zeta, Fp(1)]))

    # Compute the opening proof polynomial
    W_zeta_omega = accumulator_poly_ext3 - PolyEvalRep3.from_coeffs(Poly([accumulator_shift_zeta]))
    W_zeta_omega = W_zeta_omega / PolyEvalRep3.from_coeffs(Poly([-zeta*ROOTS[1], Fp(1)]))

    W_zeta_eval_exp = evaluate_in_exponent(CRS, W_zeta.to_coeffs())
    W_zeta_omega_eval_exp = evaluate_in_exponent(CRS, W_zeta_omega.to_coeffs())

    fifth_output = [W_zeta_eval_exp, W_zeta_omega_eval_exp]
    proof_SNARK = [first_output, second_output, third_output, fifth_output, fourth_output]
    print("Round 5 Finished with output: ", fifth_output)

    u = random_fp_seeded(str(proof_SNARK))
    return proof_SNARK, u