diff --git a/misc/prio3_multiproof_robustness.py b/poc/plot_prio3_multiproof_robustness.py similarity index 50% rename from misc/prio3_multiproof_robustness.py rename to poc/plot_prio3_multiproof_robustness.py index 0c44c56c..77a3e62f 100644 --- a/misc/prio3_multiproof_robustness.py +++ b/poc/plot_prio3_multiproof_robustness.py @@ -3,8 +3,8 @@ import matplotlib.pyplot as plt import math -FIELD128_MODULUS = 2**66 * 4611686018427387897 + 1 # Field128.MODULUS -FIELD64_MODULUS = 2**32 * 4294967295 + 1 # Field64.MODULUS +from field import Field64, Field128 +from vdaf_prio3 import Prio3SumVec NUM_REPORTS = 1000000000 @@ -22,10 +22,10 @@ def soundness(gadget_calls, gadget_degree, field_size): return gadget_calls * gadget_degree / (field_size - gadget_calls) -def robustness(epsilon, ro_queries, prep_queries, num_proofs): +def robustness(epsilon, ro_queries, prep_queries, num_proofs, seed_bits): ''' - ia.cr/2023/130, Theorem 1, ignoring negligible terms and assuming the bound - can be modified by raising `epsilon` to the power of the number of FLPs. + ia.cr/2023/130, Theorem 1, assuming the bound can be modified by raising + `epsilon` to the power of the number of FLPs. epsilon - soundness of the base FLP @@ -35,8 +35,11 @@ def robustness(epsilon, ro_queries, prep_queries, num_proofs): prep_queries - number of online attempts, a proxy for the batch size num_proofs - number of FLPs + + seed_bits - the size of the XOF seed in bits ''' - return (ro_queries + prep_queries) * epsilon**num_proofs + return (ro_queries + prep_queries) * epsilon**num_proofs + \ + (ro_queries + prep_queries**2) / 2**(seed_bits - 1) def sum_vec(field_size, num_proofs, length): @@ -45,50 +48,44 @@ def sum_vec(field_size, num_proofs, length): accepting one report in a batch of NUM_REPORTS. Assuming the asymptotically optimal chunk length. ''' + chunk_length = max(1, int(math.sqrt(length))) + vdaf = Prio3SumVec.with_params(length, 1, chunk_length) + gadget_calls = vdaf.Flp.Valid.GADGET_CALLS[0] + + base_flp_soundness = soundness(gadget_calls, 2, field_size) - # Table 11 - def gadget_calls(length, bits, chunk_length): - return (length * bits + chunk_length - 1) // chunk_length + # SumVec interprets the inner Mul-gadget outputs as coefficients of a + # polynomial and evaluates the polynomial at a random point. If a gadget + # output is non-zero, then the output is non-zero except with this + # probability. This is bounded by the number of roots of the polynomial. + circuit_soundness = length / field_size return robustness( - soundness( - gadget_calls(length, 1, max(1, math.sqrt(length))), - 2, - field_size, - ), - 2**80, # ro_queries - NUM_REPORTS, # prep_queries - num_proofs, # num_proofs + base_flp_soundness + circuit_soundness, # ia.cr/2019/188, Theorem 5.3 + 2**80, + NUM_REPORTS, + num_proofs, + vdaf.Xof.SEED_SIZE * 8, ) -print(math.log2(sum_vec(FIELD128_MODULUS, 1, 1000000))) +print(math.log2(sum_vec(Field128.MODULUS, 1, 1000000))) -lengths = range(0, 1000000, 100) +lengths = range(100, 10**5, 100) plt.plot( lengths, - [sum_vec(FIELD128_MODULUS, 1, length) for length in lengths], + [sum_vec(Field128.MODULUS, 1, length) for length in lengths], label='Field128/1', ) plt.plot( lengths, - [sum_vec(FIELD64_MODULUS, 1, length) for length in lengths], - label='Field64/1', -) -plt.plot( - lengths, - [sum_vec(FIELD64_MODULUS, 2, length) for length in lengths], + [sum_vec(Field64.MODULUS, 2, length) for length in lengths], label='Field64/2', ) plt.plot( lengths, - [sum_vec(FIELD64_MODULUS, 3, length) for length in lengths], + [sum_vec(Field64.MODULUS, 3, length) for length in lengths], label='Field64/3', ) -plt.plot( - lengths, - [sum_vec(FIELD64_MODULUS, 4, length) for length in lengths], - label='Field64/4', -) plt.xscale('log', base=10) plt.yscale('log', base=2)