Пример #1
0
def prove_low_degree(values,
                     root_of_unity,
                     maxdeg_plus_1,
                     modulus,
                     exclude_multiples_of=0):
    f = PrimeField(modulus)
    print('Proving %d values are degree <= %d' % (len(values), maxdeg_plus_1))

    # If the degree we are checking for is less than or equal to 32,
    # use the polynomial directly as a proof
    if maxdeg_plus_1 <= 16:
        print('Produced FRI proof')
        return [[x.to_bytes(32, 'big') for x in values]]

    # Calculate the set of x coordinates
    xs = get_power_cycle(root_of_unity, modulus)
    assert len(values) == len(xs)

    # Put the values into a Merkle tree. This is the root that the
    # proof will be checked against
    m = merkelize(values)

    # Select a pseudo-random x coordinate
    special_x = int.from_bytes(m[1], 'big') % modulus

    # Calculate the "column" at that x coordinate
    # (see https://vitalik.ca/general/2017/11/22/starks_part_2.html)
    # We calculate the column by Lagrange-interpolating each row, and not
    # directly from the polynomial, as this is more efficient
    quarter_len = len(xs) // 4
    x_polys = f.multi_interp_4(
        [[xs[i + quarter_len * j] for j in range(4)]
         for i in range(quarter_len)],
        [[values[i + quarter_len * j] for j in range(4)]
         for i in range(quarter_len)])
    column = [f.eval_quartic(p, special_x) for p in x_polys]
    m2 = merkelize(column)

    # Pseudo-randomly select y indices to sample
    ys = get_pseudorandom_indices(m2[1],
                                  len(column),
                                  40,
                                  exclude_multiples_of=exclude_multiples_of)

    # Compute the Merkle branches for the values in the polynomial and the column
    branches = []
    for y in ys:
        branches.append(
            [mk_branch(m2, y)] +
            [mk_branch(m, y + (len(xs) // 4) * j) for j in range(4)])

    # This component of the proof
    o = [m2[1], branches]

    # Recurse...
    return [o] + prove_low_degree(column,
                                  f.exp(root_of_unity, 4),
                                  maxdeg_plus_1 // 4,
                                  modulus,
                                  exclude_multiples_of=exclude_multiples_of)
Пример #2
0
def test_fri():
    # Pure FRI tests
    poly = list(range(4096))
    root_of_unity = pow(7, (modulus - 1) // 16384, modulus)
    evaluations = fft(poly, modulus, root_of_unity)
    proof = prove_low_degree(evaluations, root_of_unity, 4096, modulus)
    print("Approx proof length: %d" % bin_length(compress_fri(proof)))
    assert verify_low_degree_proof(
        merkelize(evaluations)[1], root_of_unity, proof, 4096, modulus)

    try:
        fakedata = [
            x if pow(3, i, 4096) > 400 else 39
            for x, i in enumerate(evaluations)
        ]
        proof2 = prove_low_degree(fakedata, root_of_unity, 4096, modulus)
        assert verify_low_degree_proof(
            merkelize(fakedata)[1], root_of_unity, proof, 4096, modulus)
        raise Exception("Fake data passed FRI")
    except:
        pass
    try:
        assert verify_low_degree_proof(
            merkelize(evaluations)[1], root_of_unity, proof, 2048, modulus)
        raise Exception("Fake data passed FRI")
    except:
        pass
Пример #3
0
def prove_low_degree(poly, root_of_unity, values, maxdeg_plus_1):
    print('Proving %d values are degree <= %d' % (len(values), maxdeg_plus_1))

    # If the degree we are checking for is less than or equal to 32,
    # use the polynomial directly as a proof
    if maxdeg_plus_1 <= 32:
        print('Produced FRI proof')
        return [[x.to_bytes(32, 'big') for x in values]]

    # Calculate the set of x coordinates
    xs = get_power_cycle(root_of_unity)

    # Put the values into a Merkle tree. This is the root that the
    # proof will be checked against
    m = merkelize(values)

    # Select a pseudo-random x coordinate
    special_x = int.from_bytes(m[1], 'big') % modulus

    # Calculate the "column" (see https://vitalik.ca/general/2017/11/22/starks_part_2.html)
    # at that x coordinate
    # We calculate the column by Lagrange-interpolating the row, and not
    # directly, as this is more efficient
    column = []
    for i in range(len(xs) // 4):
        x_poly = f.lagrange_interp(
            [values[i + len(values) * j // 4] for j in range(4)],
            [xs[i + len(xs) * j // 4] for j in range(4)])
        column.append(f.eval_poly_at(x_poly, special_x))
    m2 = merkelize(column)

    # Pseudo-randomly select y indices to sample
    ys = get_indices(m2[1], len(column), 40)

    # Compute the Merkle branches for the values in the polynomial and the column
    branches = []
    for y in ys:
        branches.append(
            [mk_branch(m2, y)] +
            [mk_branch(m, y + (len(xs) // 4) * j) for j in range(4)])

    # This component of the proof
    o = [m2[1], branches]

    # In the next iteration of the proof, we'll work with smaller roots of unity
    sub_xs = [xs[i] for i in range(0, len(xs), 4)]

    # Interpolate the polynomial for the column
    ypoly = fft(column[:len(sub_xs)],
                modulus,
                pow(root_of_unity, 4, modulus),
                inv=True)

    # Recurse...
    return [o] + prove_low_degree(ypoly, pow(root_of_unity, 4, modulus),
                                  column, maxdeg_plus_1 // 4)
Пример #4
0
def test_multi_merkle_tree():
    tree = merkelize(list(range(16)))
    for i in range(65536):
        indices = [j for j in range(16) if (i >> j) % 2 == 1]
        branch = mk_multi_branch(tree, indices)
        assert verify_multi_branch(tree[1], indices,
                                   branch) == [tree[16 + j] for j in indices]
        if i % 1024 == 1023:
            print("%d of 65536 16-element proofs checked" % (i + 1))
    print("Multi Merkle tree test passed")
Пример #5
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
Пример #6
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
Пример #7
0
def mk_mimc_proof(inp, logsteps, logprecision):
    start_time = time.time()
    assert logsteps < logprecision <= 32
    steps = 2**logsteps
    precision = 2**logprecision

    # Root of unity such that x^precision=1
    root = pow(7, (modulus-1)//precision, modulus)

    # Root of unity such that x^skips=1
    skips = precision // steps
    subroot = pow(root, skips)

    # Powers of the root of unity, our computational trace will be
    # along the sequence of roots of unity
    xs = get_power_cycle(subroot)

    # Generate the computational trace
    constants = []
    values = [inp]
    k = 1
    for i in range(steps-1):
        values.append((values[-1]**3 + (k ^ 1)) % modulus)
        constants.append(k ^ 1)
        k = (k * 9) & ((1 << 256) - 1)
    constants.append(0)
    print('Done generating computational trace')

    # Interpolate the computational trace into a polynomial
    values_polynomial = fft(values, modulus, subroot, inv=True)
    constants_polynomial = fft(constants, modulus, subroot, inv=True)
    print('Converted computational steps and constants into a polynomial')

    # Create the composed polynomial such that
    # C(P(x), P(rx), K(x)) = P(rx) - P(x)**3 - K(x)
    term1 = multiply_base(values_polynomial, subroot)
    p_evaluations = fft(values_polynomial, modulus, root)
    term2 = fft([pow(x, 3, modulus) for x in p_evaluations], modulus, root, inv=True)[:len(values_polynomial) * 3 - 2]
    c_of_values = f.sub_polys(f.sub_polys(term1, term2), constants_polynomial)
    print('Computed C(P, K) polynomial')

    # Compute D(x) = C(P(x), P(rx), K(x)) / Z(x)
    # Z(x) = (x^steps - 1) / (x - x_atlast_step)
    d = divide_by_xnm1(f.mul_polys(c_of_values,
                                   [modulus-xs[steps-1], 1]),
                       steps)
    # assert f.mul_polys(d, z) == c_of_values
    print('Computed D polynomial')

    # Evaluate D and K across the entire subgroup
    d_evaluations = fft(d, modulus, root)
    k_evaluations = fft(constants_polynomial, modulus, root)
    print('Evaluated P, D and K')

    # Compute their Merkle roots
    p_mtree = merkelize(p_evaluations)
    d_mtree = merkelize(d_evaluations)
    k_mtree = merkelize(k_evaluations)
    print('Computed hash root')

    # Based on the hashes of P and D, we select a random linear combination
    # of P * x^steps and D, and prove the low-degreeness of that, instead of proving
    # the low-degreeness of P and D separately
    k = int.from_bytes(blake(p_mtree[1] + d_mtree[1]), 'big')

    lincomb = f.add_polys(d, f.mul_by_const([0] * steps + values_polynomial, k))
    l_evaluations = fft(lincomb, modulus, root)
    l_mtree = merkelize(l_evaluations)

    print('Computed random linear combination')

    # Do some spot checks of the Merkle tree at pseudo-random coordinates
    branches = []
    samples = spot_check_security_factor // (logprecision - logsteps)
    positions = get_indices(l_mtree[1], precision - skips, samples)
    for pos in positions:
        branches.append(mk_branch(p_mtree, pos))
        branches.append(mk_branch(p_mtree, pos + skips))
        branches.append(mk_branch(d_mtree, pos))
        branches.append(mk_branch(k_mtree, pos))
        branches.append(mk_branch(l_mtree, pos))
    print('Computed %d spot checks' % samples)


    # Return the Merkle roots of P and D, the spot check Merkle proofs,
    # and low-degree proofs of P and D
    o = [p_mtree[1],
         d_mtree[1],
         k_mtree[1],
         l_mtree[1],
         branches,
         prove_low_degree(lincomb, root, l_evaluations, steps * 2)]
    print("STARK computed in %.4f sec" % (time.time() - start_time))
    return o
Пример #8
0
    # 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

# Pure FRI tests
poly = list(range(512))
root_of_unity = pow(7, (modulus-1)//1024, modulus)
evaluations = fft(poly, modulus, root_of_unity)
proof = prove_low_degree(poly, root_of_unity, evaluations, 512)
print("Approx proof length: %d" % bin_length(compress_fri(proof)))
assert verify_low_degree_proof(merkelize(evaluations)[1], root_of_unity, proof, 512)

# Compute a MIMC permutation for 2**logsteps steps, using round constants
# from the multiplicative subgroup of size 2**logprecision
def mimc(inp, logsteps, logprecision):        
    start_time = time.time()
    steps = 2**logsteps
    precision = 2**logprecision
    # Get (steps)th root of unity
    subroot = pow(7, (modulus-1)//steps, modulus)
    # We use powers of 9 mod 2^256 as the ith round constant for the moment
    k = 1
    for i in range(steps-1):
        inp = (inp**3 + (k ^ 1)) % modulus
        k = (k * 9) & ((1 << 256) - 1)
    print("MIMC computed in %.4f sec" % (time.time() - start_time))
Пример #9
0
def mk_mimc_proof(inp, steps, round_constants):
    start_time = time.time()
    # Some constraints to make our job easier
    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

    # Root of unity such that x^precision=1
    G2 = f.exp(7, (modulus-1)//precision)

    # Root of unity such that x^steps=1
    skips = precision // steps
    G1 = f.exp(G2, skips)

    # Powers of the higher-order root of unity
    xs = get_power_cycle(G2, modulus)
    last_step_position = xs[(steps-1)*extension_factor]

    # Generate the computational trace
    computational_trace = [inp]
    for i in range(steps-1):
        computational_trace.append(
            (computational_trace[-1]**3 + round_constants[i % len(round_constants)]) % modulus
        )
    output = computational_trace[-1]
    print('Done generating computational trace')

    # Interpolate the computational trace into a polynomial P, with each step
    # along a successive power of G1
    computational_trace_polynomial = fft(computational_trace, modulus, G1, inv=True)
    p_evaluations = fft(computational_trace_polynomial, modulus, G2)
    print('Converted computational steps into a polynomial and low-degree extended it')

    skips2 = steps // len(round_constants)
    constants_mini_polynomial = fft(round_constants, modulus, f.exp(G1, skips2), inv=True)
    constants_polynomial = [0 if i % skips2 else constants_mini_polynomial[i//skips2] for i in range(steps)]
    constants_mini_extension = fft(constants_mini_polynomial, modulus, f.exp(G2, skips2))
    print('Converted round constants into a polynomial and low-degree extended it')

    # Create the composed polynomial such that
    # C(P(x), P(g1*x), K(x)) = P(g1*x) - P(x)**3 - K(x)
    c_of_p_evaluations = [(p_evaluations[(i+extension_factor)%precision] -
                              f.exp(p_evaluations[i], 3) -
                              constants_mini_extension[i % len(constants_mini_extension)])
                          % modulus for i in range(precision)]
    print('Computed C(P, K) polynomial')

    # Compute D(x) = C(P(x), P(g1*x), K(x)) / Z(x)
    # Z(x) = (x^steps - 1) / (x - x_atlast_step)
    z_num_evaluations = [xs[(i * steps) % precision] - 1 for i in range(precision)]
    z_num_inv = f.multi_inv(z_num_evaluations)
    z_den_evaluations = [xs[i] - last_step_position for i in range(precision)]
    d_evaluations = [cp * zd * zni % modulus for cp, zd, zni in zip(c_of_p_evaluations, z_den_evaluations, z_num_inv)]
    print('Computed D polynomial')

    # Compute interpolant of ((1, input), (x_atlast_step, output))
    interpolant = f.lagrange_interp_2([1, last_step_position], [inp, output])
    i_evaluations = [f.eval_poly_at(interpolant, x) for x in xs]

    zeropoly2 = f.mul_polys([-1, 1], [-last_step_position, 1])
    inv_z2_evaluations = f.multi_inv([f.eval_poly_at(zeropoly2, x) for x in xs])

    b_evaluations = [((p - i) * invq) % modulus for p, i, invq in zip(p_evaluations, i_evaluations, inv_z2_evaluations)]
    print('Computed B polynomial')

    # Compute their Merkle roots
    p_mtree = merkelize(p_evaluations)
    d_mtree = merkelize(d_evaluations)
    b_mtree = merkelize(b_evaluations)
    print('Computed hash root')

    # Based on the hashes of P, D and B, we select a random linear combination
    # of P * x^steps, P, B * x^steps, B and D, and prove the low-degreeness of that,
    # instead of proving the low-degreeness of P, B and D separately
    k1 = int.from_bytes(blake(p_mtree[1] + d_mtree[1] + b_mtree[1] + b'\x01'), 'big')
    k2 = int.from_bytes(blake(p_mtree[1] + d_mtree[1] + b_mtree[1] + b'\x02'), 'big')
    k3 = int.from_bytes(blake(p_mtree[1] + d_mtree[1] + b_mtree[1] + b'\x03'), 'big')
    k4 = int.from_bytes(blake(p_mtree[1] + d_mtree[1] + b_mtree[1] + b'\x04'), 'big')

    # Compute the linear combination. We don't even both calculating it in
    # coefficient form; we just compute the evaluations
    G2_to_the_steps = f.exp(G2, steps)
    powers = [1]
    for i in range(1, precision):
        powers.append(powers[-1] * G2_to_the_steps % modulus)

    l_evaluations = [(d_evaluations[i] +
                      p_evaluations[i] * k1 + p_evaluations[i] * k2 * powers[i] +
                      b_evaluations[i] * k3 + b_evaluations[i] * powers[i] * k4) % modulus
                      for i in range(precision)]

    l_mtree = merkelize(l_evaluations)
    print('Computed random linear combination')

    # Do some spot checks of the Merkle tree at pseudo-random coordinates, excluding
    # multiples of `extension_factor`
    branches = []
    samples = spot_check_security_factor
    positions = get_pseudorandom_indices(l_mtree[1], precision, samples,
                                         exclude_multiples_of=extension_factor)
    for pos in positions:
        branches.append(mk_branch(p_mtree, pos))
        branches.append(mk_branch(p_mtree, (pos + skips) % precision))
        branches.append(mk_branch(d_mtree, pos))
        branches.append(mk_branch(b_mtree, pos))
        branches.append(mk_branch(l_mtree, pos))
    print('Computed %d spot checks' % samples)

    # Return the Merkle roots of P and D, the spot check Merkle proofs,
    # and low-degree proofs of P and D
    o = [p_mtree[1],
         d_mtree[1],
         b_mtree[1],
         l_mtree[1],
         branches,
         prove_low_degree(l_evaluations, G2, steps * 2, modulus, exclude_multiples_of=extension_factor)]
    print("STARK computed in %.4f sec" % (time.time() - start_time))
    return o
Пример #10
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')
Пример #11
0
def mk_mimc_proof(inp, logsteps, logprecision):
    start_time = time.time()
    assert logsteps < logprecision <= 32
    steps = 2**logsteps
    precision = 2**logprecision

    # Root of unity such that x^precision=1
    root = pow(7, (modulus - 1) // precision, modulus)

    # Root of unity such that x^skips=1
    skips = precision // steps
    subroot = pow(root, skips)

    # Powers of the root of unity, our computational trace will be
    # along the sequence of roots of unity
    xs = get_power_cycle(subroot)

    # Generate the computational trace
    values = [inp]
    for i in range(steps - 1):
        values.append((values[-1]**3 + xs[i]) % modulus)
    print('Done generating computational trace')

    # Interpolate the computational trace into a polynomial
    # values_polynomial = f.lagrange_interp(values, [pow(subroot, i, modulus) for i in range(steps)])
    values_polynomial = fft(values, modulus, subroot, inv=True)
    print('Computed polynomial')

    #for x, v in zip(xs, values):
    #    assert f.eval_poly_at(values_polynomial, x) == v

    # Create the composed polynomial such that
    # C(P(x), P(rx)) = P(rx) - P(x)**3 - x
    term1 = multiply_base(values_polynomial, subroot)
    term2 = fft(
        [pow(x, 3, modulus) for x in fft(values_polynomial, modulus, root)],
        modulus,
        root,
        inv=True)[:len(values_polynomial) * 3 - 2]
    c_of_values = f.sub_polys(f.sub_polys(term1, term2), [0, 1])
    print('Computed C(P) polynomial')

    # Compute D(x) = C(P(x)) / Z(x)
    # Z(x) = (x^steps - 1) / (x - x_atlast_step)
    d = divide_by_xnm1(f.mul_polys(c_of_values, [modulus - xs[steps - 1], 1]),
                       steps)
    # assert f.mul_polys(d, z) == c_of_values
    print('Computed D polynomial')

    # Evaluate P and D across the entire subgroup
    p_evaluations = fft(values_polynomial, modulus, root)
    d_evaluations = fft(d, modulus, root)
    print('Evaluated P and D')

    # Compute their Merkle roots
    p_mtree = merkelize(p_evaluations)
    d_mtree = merkelize(d_evaluations)
    print('Computed hash root')

    # Do some spot checks of the Merkle tree at pseudo-random coordinates
    branches = []
    samples = spot_check_security_factor // (logprecision - logsteps)
    positions = get_indices(blake(p_mtree[1] + d_mtree[1]), precision - skips,
                            samples)
    for pos in positions:
        branches.append(mk_branch(p_mtree, pos))
        branches.append(mk_branch(p_mtree, pos + skips))
        branches.append(mk_branch(d_mtree, pos))
    print('Computed %d spot checks' % samples)

    while len(d) < steps * 2:
        d += [0]

    # Return the Merkle roots of P and D, the spot check Merkle proofs,
    # and low-degree proofs of P and D
    o = [
        p_mtree[1], d_mtree[1], branches,
        prove_low_degree(values_polynomial, root, p_evaluations, steps),
        prove_low_degree(d, root, d_evaluations, steps * 2)
    ]
    print("STARK computed in %.4f sec" % (time.time() - start_time))
    return o
Пример #12
0
    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


# Pure FRI tests
poly = list(range(512))
root_of_unity = pow(7, (modulus - 1) // 1024, modulus)
evaluations = fft(poly, modulus, root_of_unity)
proof = prove_low_degree(poly, root_of_unity, evaluations, 512)
print("Approx proof length: %d" % bin_length(compress_fri(proof)))
assert verify_low_degree_proof(
    merkelize(evaluations)[1], root_of_unity, proof, 512)


# Compute a MIMC permutation for 2**logsteps steps, using round constants
# from the multiplicative subgroup of size 2**logprecision
def mimc(inp, logsteps, logprecision):
    start_time = time.time()
    steps = 2**logsteps
    precision = 2**logprecision
    # Get (steps)th root of unity
    subroot = pow(7, (modulus - 1) // steps, modulus)
    xs = get_power_cycle(subroot)
    for i in range(steps - 1):
        inp = (inp**3 + xs[i]) % modulus
    print("MIMC computed in %.4f sec" % (time.time() - start_time))
    return inp
Пример #13
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')