Example #1
0
def verify_mimc_proof(inp, logsteps, logprecision, output, proof):
    p_root, d_root, branches, p_proof, d_proof = proof
    start_time = time.time()

    steps = 2**logsteps
    precision = 2**logprecision

    # Get (steps)th root of unity
    root_of_unity = pow(7, (modulus - 1) // precision, modulus)
    skips = precision // steps

    # Verifies the low-degree proofs
    assert verify_low_degree_proof(p_root, root_of_unity, p_proof, steps)
    assert verify_low_degree_proof(d_root, root_of_unity, d_proof, steps * 2)

    # Performs the spot checks
    samples = spot_check_security_factor // (logprecision - logsteps)
    positions = get_indices(blake(p_root + d_root), precision - skips, samples)
    for i, pos in enumerate(positions):

        # Check C(P(x)) = Z(x) * D(x)
        x = pow(root_of_unity, pos, modulus)
        p_of_x = verify_branch(p_root, pos, branches[i * 3])
        p_of_rx = verify_branch(p_root, pos + skips, branches[i * 3 + 1])
        d_of_x = verify_branch(d_root, pos, branches[i * 3 + 2])
        zvalue = f.div(
            pow(x, steps, modulus) - 1, x - pow(root_of_unity,
                                                (steps - 1) * skips, modulus))
        assert (p_of_rx - p_of_x**3 - x - zvalue * d_of_x) % modulus == 0

    print('Verified %d consistency checks' % (spot_check_security_factor //
                                              (logprecision - logsteps)))
    print('Verified STARK in %.4f sec' % (time.time() - start_time))
    return True
Example #2
0
def verify_mimc_proof(inp, steps, round_constants, output, proof):
    p_root, d_root, b_root, l_root, branches, fri_proof = proof
    start_time = time.time()
    assert steps <= 2**32 // extension_factor
    assert is_a_power_of_2(steps) and is_a_power_of_2(len(round_constants))
    assert len(round_constants) < steps

    precision = steps * extension_factor

    # Get (steps)th root of unity
    G2 = f.exp(7, (modulus-1)//precision)
    skips = precision // steps

    # Gets the polynomial representing the round constants
    skips2 = steps // len(round_constants)
    constants_mini_polynomial = fft(round_constants, modulus, f.exp(G2, extension_factor * skips2), inv=True)

    # Verifies the low-degree proofs
    assert verify_low_degree_proof(l_root, G2, fri_proof, steps * 2, modulus, exclude_multiples_of=extension_factor)

    # Performs the spot checks
    k1 = int.from_bytes(blake(p_root + d_root + b_root + b'\x01'), 'big')
    k2 = int.from_bytes(blake(p_root + d_root + b_root + b'\x02'), 'big')
    k3 = int.from_bytes(blake(p_root + d_root + b_root + b'\x03'), 'big')
    k4 = int.from_bytes(blake(p_root + d_root + b_root + b'\x04'), 'big')
    samples = spot_check_security_factor
    positions = get_pseudorandom_indices(l_root, precision, samples,
                                         exclude_multiples_of=extension_factor)
    last_step_position = f.exp(G2, (steps - 1) * skips)
    for i, pos in enumerate(positions):
        x = f.exp(G2, pos)
        x_to_the_steps = f.exp(x, steps)
        p_of_x = verify_branch(p_root, pos, branches[i*5])
        p_of_g1x = verify_branch(p_root, (pos+skips)%precision, branches[i*5 + 1])
        d_of_x = verify_branch(d_root, pos, branches[i*5 + 2])
        b_of_x = verify_branch(b_root, pos, branches[i*5 + 3])
        l_of_x = verify_branch(l_root, pos, branches[i*5 + 4])

        zvalue = f.div(f.exp(x, steps) - 1,
                       x - last_step_position)
        k_of_x = f.eval_poly_at(constants_mini_polynomial, f.exp(x, skips2))

        # Check transition constraints C(P(x)) = Z(x) * D(x)
        assert (p_of_g1x - p_of_x ** 3 - k_of_x - zvalue * d_of_x) % modulus == 0

        # Check boundary constraints B(x) * Q(x) + I(x) = P(x)
        interpolant = f.lagrange_interp_2([1, last_step_position], [inp, output])
        zeropoly2 = f.mul_polys([-1, 1], [-last_step_position, 1])
        assert (p_of_x - b_of_x * f.eval_poly_at(zeropoly2, x) -
                f.eval_poly_at(interpolant, x)) % modulus == 0

        # Check correctness of the linear combination
        assert (l_of_x - d_of_x - 
                k1 * p_of_x - k2 * p_of_x * x_to_the_steps -
                k3 * b_of_x - k4 * b_of_x * x_to_the_steps) % modulus == 0

    print('Verified %d consistency checks' % spot_check_security_factor)
    print('Verified STARK in %.4f sec' % (time.time() - start_time))
    return True
Example #3
0
def verify_mimc_proof(inp, logsteps, logprecision, output, proof):
    p_root, d_root, k_root, l_root, branches, fri_proof = proof
    start_time = time.time()

    steps = 2**logsteps
    precision = 2**logprecision

    # Get (steps)th root of unity
    root_of_unity = pow(7, (modulus-1)//precision, modulus)
    skips = precision // steps

    # Verifies the low-degree proofs
    assert verify_low_degree_proof(l_root, root_of_unity, fri_proof, steps * 2)

    # Performs the spot checks
    k = int.from_bytes(blake(p_root + d_root), 'big')
    samples = spot_check_security_factor // (logprecision - logsteps)
    positions = get_indices(l_root, precision - skips, samples)
    for i, pos in enumerate(positions):

        # Check C(P(x)) = Z(x) * D(x)
        x = pow(root_of_unity, pos, modulus)
        p_of_x = verify_branch(p_root, pos, branches[i*5])
        p_of_rx = verify_branch(p_root, pos+skips, branches[i*5 + 1])
        d_of_x = verify_branch(d_root, pos, branches[i*5 + 2])
        k_of_x = verify_branch(k_root, pos, branches[i*5 + 3])
        l_of_x = verify_branch(l_root, pos, branches[i*5 + 4])
        zvalue = f.div(pow(x, steps, modulus) - 1,
                       x - pow(root_of_unity, (steps - 1) * skips, modulus))
        assert (p_of_rx - p_of_x ** 3 - k_of_x - zvalue * d_of_x) % modulus == 0
        assert (l_of_x - d_of_x - k * p_of_x * pow(x, steps, modulus)) % modulus == 0

    print('Verified %d consistency checks' % (spot_check_security_factor // (logprecision - logsteps)))
    print('Verified STARK in %.4f sec' % (time.time() - start_time))
    print('Note: this does not include verifying the Merkle root of the constants tree')
    print('This can be done by every client once as a precomputation')
    return True
Example #4
0
def verify_low_degree_proof(merkle_root, root_of_unity, proof, maxdeg_plus_1, modulus, exclude_multiples_of=0):
    f = PrimeField(modulus)

    # Calculate which root of unity we're working with
    testval = root_of_unity
    roudeg = 1
    while testval != 1:
        roudeg *= 2
        testval = (testval * testval) % modulus

    # Powers of the given root of unity 1, p, p**2, p**3 such that p**4 = 1
    quartic_roots_of_unity = [1,
                              f.exp(root_of_unity, roudeg // 4),
                              f.exp(root_of_unity, roudeg // 2),
                              f.exp(root_of_unity, roudeg * 3 // 4)]

    # Verify the recursive components of the proof
    for prf in proof[:-1]:
        root2, branches = prf
        print('Verifying degree <= %d' % maxdeg_plus_1)

        # Calculate the pseudo-random x coordinate
        special_x = int.from_bytes(merkle_root, 'big') % modulus

        # Calculate the pseudo-randomly sampled y indices
        ys = get_pseudorandom_indices(root2, roudeg // 4, 40,
                                      exclude_multiples_of=exclude_multiples_of)

        # For each y coordinate, get the x coordinates on the row, the values on
        # the row, and the value at that y from the column
        xcoords = []
        rows = []
        columnvals = []
        for i, y in enumerate(ys):
            # The x coordinates from the polynomial
            x1 = f.exp(root_of_unity, y)
            xcoords.append([(quartic_roots_of_unity[j] * x1) % modulus for j in range(4)])

            # The values from the original polynomial
            row = [verify_branch(merkle_root, y + (roudeg // 4) * j, prf)
                   for j, prf in zip(range(4), branches[i][1:])]
            rows.append(row)

            columnvals.append(verify_branch(root2, y, branches[i][0]))

        # Verify for each selected y coordinate that the four points from the
        # polynomial and the one point from the column that are on that y 
        # coordinate are on the same deg < 4 polynomial
        polys = f.multi_interp_4(xcoords, rows)

        for p, c in zip(polys, columnvals):
            assert f.eval_quartic(p, special_x) == c

        # Update constants to check the next proof
        merkle_root = root2
        root_of_unity = f.exp(root_of_unity, 4)
        maxdeg_plus_1 //= 4
        roudeg //= 4

    # Verify the direct components of the proof
    data = [int.from_bytes(x, 'big') for x in proof[-1]]
    print('Verifying degree <= %d' % maxdeg_plus_1)
    assert maxdeg_plus_1 <= 16

    # Check the Merkle root matches up
    mtree = merkelize(data)
    assert mtree[1] == merkle_root

    # Check the degree of the data
    powers = get_power_cycle(root_of_unity, modulus)
    if exclude_multiples_of:
        pts = [x for x in range(len(data)) if x % exclude_multiples_of]
    else:
        pts = range(len(data))

    poly = f.lagrange_interp([powers[x] for x in pts[:maxdeg_plus_1]],
                             [data[x] for x in pts[:maxdeg_plus_1]])
    for x in pts[maxdeg_plus_1:]:
        assert f.eval_poly_at(poly, powers[x]) == data[x]   

    print('FRI proof verified')
    return True
Example #5
0
def verify_low_degree_proof(merkle_root, root_of_unity, proof, maxdeg_plus_1):

    # Calculate which root of unity we're working with
    testval = root_of_unity
    roudeg = 1
    while testval != 1:
        roudeg *= 2
        testval = (testval * testval) % modulus

    # Verify the recursive components of the proof
    for prf in proof[:-1]:
        root2, branches = prf
        print('Verifying degree <= %d' % maxdeg_plus_1)

        # Calculate the pseudo-random x coordinate
        special_x = int.from_bytes(merkle_root, 'big') % modulus

        # Calculate the pseudo-randomly sampled y indices
        ys = get_indices(root2, roudeg // 4, 40)


        # Verify for each selected y coordinate that the four points from the polynomial
        # and the one point from the column that are on that y coordinate are on the same
        # deg < 4 polynomial
        for i, y in enumerate(ys):
            # The x coordinates from the polynomial
            x1 = pow(root_of_unity, y, modulus)
            xcoords = [(quartic_roots_of_unity[j] * x1) % modulus for j in range(4)]

            # The values from the polynomial
            row = [verify_branch(merkle_root, y + (roudeg // 4) * j, prf) for j, prf in zip(range(4), branches[i][1:])]

            # Verify proof and recover the column value
            values = [verify_branch(root2, y, branches[i][0])] + row

            # Lagrange interpolate and check deg is < 4
            p = lagrange_interp_4(row, xcoords, modulus)
            assert f.eval_poly_at(p, special_x) == verify_branch(root2, y, branches[i][0])

        # Update constants to check the next proof
        merkle_root = root2
        root_of_unity = pow(root_of_unity, 4, modulus)
        maxdeg_plus_1 //= 4
        roudeg //= 4

    # Verify the direct components of the proof
    data = [int.from_bytes(x, 'big') for x in proof[-1]]
    print('Verifying degree <= %d' % maxdeg_plus_1)
    assert maxdeg_plus_1 <= 32

    # Check the Merkle root matches up
    mtree = merkelize(data)
    assert mtree[1] == merkle_root

    # Check the degree of the data
    poly = fft(data, modulus, root_of_unity, inv=True)
    for i in range(maxdeg_plus_1, len(poly)):
        assert poly[i] == 0

    print('FRI proof verified')
    return True
Example #6
0
def test_merkletree():
    t = merkelize(range(128))
    b = mk_branch(t, 59)
    assert verify_branch(t[1], 59, b) == 59
    print('Merkle tree works')
Example #7
0
def test_merkletree():
    t = merkelize([x.to_bytes(32, 'big') for x in range(128)])
    b = mk_branch(t, 59)
    assert verify_branch(t[1], 59, b, output_as_int=True) == 59
    print('Merkle tree works')