generated from martinthomson/internet-draft-template
-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Strengthen recommendation about field size
The security consideration section has the following recommendation for choosing parameters for circuits with joint randomness: "Field128 is RECOMMENDED, but Field64 MAY be used with at least three proofs". Clarify where this requirement comes from (the base proof system needs around 128 bits of security) and strengthen this language somewhat: "Either Field128 or Field64 with three proofs MUST be used".
- Loading branch information
Showing
2 changed files
with
83 additions
and
78 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,110 +1,103 @@ | ||
# plot_prio3_multiproof_robustness.py - Plot robustness bounds for various | ||
# parameters. | ||
# Use `sage -python plot_prio3_multiproof_robustness.py` | ||
# Plot robustness bounds for various parameters. | ||
# | ||
# sage -python plot_prio3_multiproof_robustness.py | ||
import math | ||
from typing import cast | ||
from typing import TypeVar | ||
|
||
import matplotlib.pyplot as plt | ||
|
||
from vdaf_poc.field import Field64, Field128 | ||
from vdaf_poc.flp_bbcggi19 import FlpBBCGGI19 | ||
from vdaf_poc.vdaf_prio3 import Prio3SumVec | ||
from vdaf_poc.field import Field64, Field128, NttField | ||
from vdaf_poc.flp_bbcggi19 import FlpBBCGGI19, SumVec | ||
|
||
NUM_REPORTS = 1000000000 | ||
Measurement = TypeVar("Measurement") | ||
AggResult = TypeVar("AggResult") | ||
F = TypeVar("F", bound=NttField) | ||
|
||
|
||
def soundness(gadget_calls: int, gadget_degree: int, field_size: int) -> float: | ||
def base_soundness(flp: FlpBBCGGI19[Measurement, AggResult, F]) -> float: | ||
''' | ||
ia.cr/2019/188, Theorem 4.3 | ||
gadget_calls - number of times the gadget is called | ||
gadget_degree - arithmetic degree of the gadget | ||
field_size - size of the field | ||
''' | ||
return gadget_calls * gadget_degree / (field_size - gadget_calls) | ||
return sum((g_calls * g.DEGREE) / (flp.field.MODULUS - g_calls) | ||
for (g, g_calls) in zip(flp.valid.GADGETS, flp.valid.GADGET_CALLS)) | ||
|
||
|
||
def robustness( | ||
epsilon: float, | ||
soundness: float, | ||
ro_queries: int, | ||
prep_queries: int, | ||
num_proofs: int, | ||
seed_bits: int) -> float: | ||
num_proofs: int) -> float: | ||
''' | ||
ia.cr/2023/130, Theorem 1, assuming the bound can be modified by raising | ||
`epsilon` to the power of the number of FLPs. | ||
`epsilon` to the power of the number of FLPs. We're also assuming the first | ||
term dominates, i.e., we're ignoring the seed size. | ||
epsilon - soundness of the base FLP | ||
soundness - soundness of the FLP | ||
ro_queries - random oracle queries, a proxy for the amount of | ||
precomputation done by the adversary | ||
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 + \ | ||
(ro_queries + prep_queries**2) / 2**(seed_bits - 1) | ||
return (ro_queries + prep_queries) * soundness**num_proofs | ||
|
||
|
||
def sum_vec(field_size: int, num_proofs: int, length: int) -> float: | ||
def sum_vec(field: type[NttField], num_proofs: int, length: int) -> float: | ||
''' | ||
Prio3SumVec (draft-irtf-cfrg-vdaf-08, Section 7.4.3): Probability of | ||
accepting one report in a batch of NUM_REPORTS. Assuming the asymptotically | ||
optimal chunk length. | ||
Maximum probability of at least 1 in 1 billion attacks on Prio3SumVec | ||
robustness succeeding after doing 2^80 random oracle queries. | ||
''' | ||
bits = 1 | ||
chunk_length = max(1, length**(1/2)) | ||
vdaf = Prio3SumVec(2, length, bits, chunk_length) | ||
valid = cast(FlpBBCGGI19[list[int], list[int], Field128], vdaf.flp).valid | ||
gadget_calls = valid.GADGET_CALLS[0] | ||
gadget_degree = valid.GADGETS[0].DEGREE | ||
|
||
base_flp_soundness = soundness(gadget_calls, gadget_degree, field_size) | ||
flp = FlpBBCGGI19(SumVec(field, length, bits, 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 * bits / field_size | ||
# Assuming we adopt the improvement from | ||
# https://github.com/cfrg/draft-irtf-cfrg-vdaf/issues/427 | ||
soundness = chunk_length / field.MODULUS + base_soundness(flp) | ||
|
||
return robustness( | ||
base_flp_soundness + circuit_soundness, # ia.cr/2019/188, Theorem 5.3 | ||
2**80, | ||
NUM_REPORTS, | ||
soundness, | ||
2**80, # ro queries | ||
1_000_000_000, # prep queries | ||
num_proofs, | ||
vdaf.xof.SEED_SIZE * 8, | ||
) | ||
|
||
|
||
print(math.log2(sum_vec(Field128.MODULUS, 1, 100000))) | ||
|
||
lengths = range(100, 10**6, 100) | ||
plt.plot( | ||
lengths, | ||
[sum_vec(Field128.MODULUS, 1, length) for length in lengths], | ||
label='Field128/1', | ||
) | ||
plt.plot( | ||
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], | ||
label='Field64/3', | ||
) | ||
|
||
plt.xscale('log', base=10) | ||
plt.yscale('log', base=2) | ||
plt.xlabel('Length') | ||
plt.ylabel('Prob(1 in {} accepted reports being invalid)'.format(NUM_REPORTS)) | ||
plt.title('Prio3SumvVec (field/number of proofs)') | ||
plt.legend() | ||
plt.grid() | ||
plt.show() | ||
if __name__ == '__main__': | ||
print(-math.log2(sum_vec(Field128, 1, 100_000))) | ||
print(-math.log2(sum_vec(Field64, 3, 100_000))) | ||
print(-math.log2(sum_vec(Field64, 2, 100_000))) | ||
print(-math.log2(sum_vec(Field64, 1, 100_000))) | ||
|
||
lengths = range(100, 10**6, 100) | ||
plt.plot( | ||
lengths, | ||
[sum_vec(Field128, 1, length) for length in lengths], | ||
label='Field128/1', | ||
) | ||
plt.plot( | ||
lengths, | ||
[sum_vec(Field64, 3, length) for length in lengths], | ||
label='Field64/3', | ||
) | ||
plt.plot( | ||
lengths, | ||
[sum_vec(Field64, 2, length) for length in lengths], | ||
label='Field64/2', | ||
) | ||
# plt.plot( | ||
# lengths, | ||
# [sum_vec(Field64, 1, length) for length in lengths], | ||
# label='Field64/1', | ||
# ) | ||
|
||
plt.xscale('log', base=10) | ||
plt.yscale('log', base=2) | ||
plt.xlabel('Length') | ||
plt.ylabel('Prob') | ||
plt.title('Prio3SumvVec (field/number of proofs)') | ||
plt.legend() | ||
plt.grid() | ||
plt.show() |