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
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