Optimized proof size down by 1/8 or so
This commit is contained in:
parent
63599737d1
commit
cf7e8e1e63
|
@ -98,11 +98,11 @@ def verify_low_degree_proof(merkle_root, root_of_unity, proof, maxdeg_plus_1, mo
|
||||||
xcoords.append([(quartic_roots_of_unity[j] * x1) % modulus for j in range(4)])
|
xcoords.append([(quartic_roots_of_unity[j] * x1) % modulus for j in range(4)])
|
||||||
|
|
||||||
# The values from the original polynomial
|
# The values from the original polynomial
|
||||||
row = [verify_branch(merkle_root, y + (roudeg // 4) * j, prf)
|
row = [verify_branch(merkle_root, y + (roudeg // 4) * j, prf, output_as_int=True)
|
||||||
for j, prf in zip(range(4), branches[i][1:])]
|
for j, prf in zip(range(4), branches[i][1:])]
|
||||||
rows.append(row)
|
rows.append(row)
|
||||||
|
|
||||||
columnvals.append(verify_branch(root2, y, branches[i][0]))
|
columnvals.append(verify_branch(root2, y, branches[i][0], output_as_int=True))
|
||||||
|
|
||||||
# Verify for each selected y coordinate that the four points from the
|
# 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
|
# polynomial and the one point from the column that are on that y
|
||||||
|
|
|
@ -5,7 +5,7 @@ except:
|
||||||
blake = lambda x: blake2s(x).digest()
|
blake = lambda x: blake2s(x).digest()
|
||||||
|
|
||||||
def merkelize(L):
|
def merkelize(L):
|
||||||
nodes = [b''] * len(L) + [x.to_bytes(32, 'big') for x in L]
|
nodes = [b''] * len(L) + [x.to_bytes(32, 'big') if isinstance(x, int) else x for x in L]
|
||||||
for i in range(len(L) - 1, 0, -1):
|
for i in range(len(L) - 1, 0, -1):
|
||||||
nodes[i] = blake(nodes[i*2] + nodes[i*2+1])
|
nodes[i] = blake(nodes[i*2] + nodes[i*2+1])
|
||||||
return nodes
|
return nodes
|
||||||
|
@ -18,7 +18,7 @@ def mk_branch(tree, index):
|
||||||
index //= 2
|
index //= 2
|
||||||
return o
|
return o
|
||||||
|
|
||||||
def verify_branch(root, index, proof):
|
def verify_branch(root, index, proof, output_as_int=False):
|
||||||
index += 2**len(proof)
|
index += 2**len(proof)
|
||||||
v = proof[0]
|
v = proof[0]
|
||||||
for p in proof[1:]:
|
for p in proof[1:]:
|
||||||
|
@ -28,6 +28,6 @@ def verify_branch(root, index, proof):
|
||||||
v = blake(v + p)
|
v = blake(v + p)
|
||||||
index //= 2
|
index //= 2
|
||||||
assert v == root
|
assert v == root
|
||||||
return int.from_bytes(proof[0], 'big')
|
return int.from_bytes(proof[0], 'big') if output_as_int else proof[0]
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -89,19 +89,20 @@ def mk_mimc_proof(inp, steps, round_constants):
|
||||||
b_evaluations = [((p - i) * invq) % modulus for p, i, invq in zip(p_evaluations, i_evaluations, inv_z2_evaluations)]
|
b_evaluations = [((p - i) * invq) % modulus for p, i, invq in zip(p_evaluations, i_evaluations, inv_z2_evaluations)]
|
||||||
print('Computed B polynomial')
|
print('Computed B polynomial')
|
||||||
|
|
||||||
# Compute their Merkle roots
|
# Compute their Merkle root
|
||||||
p_mtree = merkelize(p_evaluations)
|
mtree = merkelize([pval.to_bytes(32, 'big') +
|
||||||
d_mtree = merkelize(d_evaluations)
|
dval.to_bytes(32, 'big') +
|
||||||
b_mtree = merkelize(b_evaluations)
|
bval.to_bytes(32, 'big') for
|
||||||
|
pval, dval, bval in zip(p_evaluations, d_evaluations, b_evaluations)])
|
||||||
print('Computed hash root')
|
print('Computed hash root')
|
||||||
|
|
||||||
# Based on the hashes of P, D and B, we select a random linear combination
|
# 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,
|
# 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
|
# 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')
|
k1 = int.from_bytes(blake(mtree[1] + b'\x01'), 'big')
|
||||||
k2 = int.from_bytes(blake(p_mtree[1] + d_mtree[1] + b_mtree[1] + b'\x02'), 'big')
|
k2 = int.from_bytes(blake(mtree[1] + b'\x02'), 'big')
|
||||||
k3 = int.from_bytes(blake(p_mtree[1] + d_mtree[1] + b_mtree[1] + b'\x03'), 'big')
|
k3 = int.from_bytes(blake(mtree[1] + b'\x03'), 'big')
|
||||||
k4 = int.from_bytes(blake(p_mtree[1] + d_mtree[1] + b_mtree[1] + b'\x04'), 'big')
|
k4 = int.from_bytes(blake(mtree[1] + b'\x04'), 'big')
|
||||||
|
|
||||||
# Compute the linear combination. We don't even both calculating it in
|
# Compute the linear combination. We don't even both calculating it in
|
||||||
# coefficient form; we just compute the evaluations
|
# coefficient form; we just compute the evaluations
|
||||||
|
@ -125,18 +126,14 @@ def mk_mimc_proof(inp, steps, round_constants):
|
||||||
positions = get_pseudorandom_indices(l_mtree[1], precision, samples,
|
positions = get_pseudorandom_indices(l_mtree[1], precision, samples,
|
||||||
exclude_multiples_of=extension_factor)
|
exclude_multiples_of=extension_factor)
|
||||||
for pos in positions:
|
for pos in positions:
|
||||||
branches.append(mk_branch(p_mtree, pos))
|
branches.append(mk_branch(mtree, pos))
|
||||||
branches.append(mk_branch(p_mtree, (pos + skips) % precision))
|
branches.append(mk_branch(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))
|
branches.append(mk_branch(l_mtree, pos))
|
||||||
print('Computed %d spot checks' % samples)
|
print('Computed %d spot checks' % samples)
|
||||||
|
|
||||||
# Return the Merkle roots of P and D, the spot check Merkle proofs,
|
# Return the Merkle roots of P and D, the spot check Merkle proofs,
|
||||||
# and low-degree proofs of P and D
|
# and low-degree proofs of P and D
|
||||||
o = [p_mtree[1],
|
o = [mtree[1],
|
||||||
d_mtree[1],
|
|
||||||
b_mtree[1],
|
|
||||||
l_mtree[1],
|
l_mtree[1],
|
||||||
branches,
|
branches,
|
||||||
prove_low_degree(l_evaluations, G2, steps * 2, modulus, exclude_multiples_of=extension_factor)]
|
prove_low_degree(l_evaluations, G2, steps * 2, modulus, exclude_multiples_of=extension_factor)]
|
||||||
|
@ -145,7 +142,7 @@ def mk_mimc_proof(inp, steps, round_constants):
|
||||||
|
|
||||||
# Verifies a STARK
|
# Verifies a STARK
|
||||||
def verify_mimc_proof(inp, steps, round_constants, output, proof):
|
def verify_mimc_proof(inp, steps, round_constants, output, proof):
|
||||||
p_root, d_root, b_root, l_root, branches, fri_proof = proof
|
m_root, l_root, branches, fri_proof = proof
|
||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
assert steps <= 2**32 // extension_factor
|
assert steps <= 2**32 // extension_factor
|
||||||
assert is_a_power_of_2(steps) and is_a_power_of_2(len(round_constants))
|
assert is_a_power_of_2(steps) and is_a_power_of_2(len(round_constants))
|
||||||
|
@ -165,10 +162,10 @@ def verify_mimc_proof(inp, steps, round_constants, output, proof):
|
||||||
assert verify_low_degree_proof(l_root, G2, fri_proof, steps * 2, modulus, exclude_multiples_of=extension_factor)
|
assert verify_low_degree_proof(l_root, G2, fri_proof, steps * 2, modulus, exclude_multiples_of=extension_factor)
|
||||||
|
|
||||||
# Performs the spot checks
|
# Performs the spot checks
|
||||||
k1 = int.from_bytes(blake(p_root + d_root + b_root + b'\x01'), 'big')
|
k1 = int.from_bytes(blake(m_root + b'\x01'), 'big')
|
||||||
k2 = int.from_bytes(blake(p_root + d_root + b_root + b'\x02'), 'big')
|
k2 = int.from_bytes(blake(m_root + b'\x02'), 'big')
|
||||||
k3 = int.from_bytes(blake(p_root + d_root + b_root + b'\x03'), 'big')
|
k3 = int.from_bytes(blake(m_root + b'\x03'), 'big')
|
||||||
k4 = int.from_bytes(blake(p_root + d_root + b_root + b'\x04'), 'big')
|
k4 = int.from_bytes(blake(m_root + b'\x04'), 'big')
|
||||||
samples = spot_check_security_factor
|
samples = spot_check_security_factor
|
||||||
positions = get_pseudorandom_indices(l_root, precision, samples,
|
positions = get_pseudorandom_indices(l_root, precision, samples,
|
||||||
exclude_multiples_of=extension_factor)
|
exclude_multiples_of=extension_factor)
|
||||||
|
@ -176,11 +173,14 @@ def verify_mimc_proof(inp, steps, round_constants, output, proof):
|
||||||
for i, pos in enumerate(positions):
|
for i, pos in enumerate(positions):
|
||||||
x = f.exp(G2, pos)
|
x = f.exp(G2, pos)
|
||||||
x_to_the_steps = f.exp(x, steps)
|
x_to_the_steps = f.exp(x, steps)
|
||||||
p_of_x = verify_branch(p_root, pos, branches[i*5])
|
mbranch1 = verify_branch(m_root, pos, branches[i*3])
|
||||||
p_of_g1x = verify_branch(p_root, (pos+skips)%precision, branches[i*5 + 1])
|
mbranch2 = verify_branch(m_root, (pos+skips)%precision, branches[i*3+1])
|
||||||
d_of_x = verify_branch(d_root, pos, branches[i*5 + 2])
|
l_of_x = verify_branch(l_root, pos, branches[i*3 + 2], output_as_int=True)
|
||||||
b_of_x = verify_branch(b_root, pos, branches[i*5 + 3])
|
|
||||||
l_of_x = verify_branch(l_root, pos, branches[i*5 + 4])
|
p_of_x = int.from_bytes(mbranch1[:32], 'big')
|
||||||
|
p_of_g1x = int.from_bytes(mbranch2[:32], 'big')
|
||||||
|
d_of_x = int.from_bytes(mbranch1[32:64], 'big')
|
||||||
|
b_of_x = int.from_bytes(mbranch1[64:], 'big')
|
||||||
|
|
||||||
zvalue = f.div(f.exp(x, steps) - 1,
|
zvalue = f.div(f.exp(x, steps) - 1,
|
||||||
x - last_step_position)
|
x - last_step_position)
|
||||||
|
|
|
@ -5,9 +5,9 @@ from merkle_tree import merkelize, mk_branch, verify_branch
|
||||||
from fri import prove_low_degree, verify_low_degree_proof
|
from fri import prove_low_degree, verify_low_degree_proof
|
||||||
|
|
||||||
def test_merkletree():
|
def test_merkletree():
|
||||||
t = merkelize(range(128))
|
t = merkelize([x.to_bytes(32, 'big') for x in range(128)])
|
||||||
b = mk_branch(t, 59)
|
b = mk_branch(t, 59)
|
||||||
assert verify_branch(t[1], 59, b) == 59
|
assert verify_branch(t[1], 59, b, output_as_int=True) == 59
|
||||||
print('Merkle tree works')
|
print('Merkle tree works')
|
||||||
|
|
||||||
def test_fri():
|
def test_fri():
|
||||||
|
@ -41,7 +41,7 @@ def test_stark():
|
||||||
#constants = [random.randrange(modulus) for i in range(64)]
|
#constants = [random.randrange(modulus) for i in range(64)]
|
||||||
constants = [(i**7) ^ 42 for i in range(64)]
|
constants = [(i**7) ^ 42 for i in range(64)]
|
||||||
proof = mk_mimc_proof(INPUT, 2**LOGSTEPS, constants)
|
proof = mk_mimc_proof(INPUT, 2**LOGSTEPS, constants)
|
||||||
p_root, d_root, b_root, l_root, branches, fri_proof = proof
|
m_root, l_root, branches, fri_proof = proof
|
||||||
L1 = bin_length(compress_branches(branches))
|
L1 = bin_length(compress_branches(branches))
|
||||||
L2 = bin_length(compress_fri(fri_proof))
|
L2 = bin_length(compress_fri(fri_proof))
|
||||||
print("Approx proof length: %d (branches), %d (FRI proof), %d (total)" % (L1, L2, L1 + L2))
|
print("Approx proof length: %d (branches), %d (FRI proof), %d (total)" % (L1, L2, L1 + L2))
|
||||||
|
|
Loading…
Reference in New Issue