-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve wraparound check parameter search #81
Conversation
Even with
|
1dc077c
to
edaf8d6
Compare
edaf8d6
to
33e57e2
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I haven't worked my way through the code all the way yet, but I have a lot of comments and wanted to pause here. Two high level things:
- The code interleaves pretty printing with the actual logic for computing the parameters. It would be better if the parameters were computed first and stored in some data structure, then the data structure gets printted. That way the reader isn't distracted by irrelevant code.
- Let's get rid of the code for generating CSV. Note that I had suggested in an earlier PR that this might be more useful than pretty printing: I meant that we should do one or the other, not both. Let's wait to write code until we need it. If you prefer pretty printing, let's go with that.
a393c5a
to
f3a30bd
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I refactored the code more based on the feedbacks:
- I decoupled the search logic and printing logic, so now there are two functions that do the searching:
search_wr_params
andsearch_vdaf_params
(not sure about the name of the second one, it's basically computing the number of proofs for FLP soundness), and for printing:display_wr_params
anddisplay_vdaf_params
. - I won't compute the
max_alpha
given Lemma 3.3. Instead I used a fixedmax_alpha
, e.g., 10, and then do the binary searching ofalpha
betweenmin_alpha
andmax_alpha
, and delegate the field size checking of eachalpha
toPineValid.__init__
. This makes the program a little more inefficient, but a lot cleaner, since we can leave Lemma 3.3 logic inPineValid.__init__
completely. - Removed
bin_pmf
, instead I binary searchnum_wr_successes
. This still runs reasonably fast. - Added more code comments.
I squashed commits, since reviewing the new diff on top of the initial diff might get really confusing.
With
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Huge improvement, thanks for the hard work. One blocking change request, which is to preoprly compute Field48.gf
(likewise for Field56.gf
).
poc/find_wr_params.sage
Outdated
ENCODED_SIZE = 6 | ||
|
||
# Operational parameters | ||
gf = Field64.gf |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Likewise below.
gf = Field64.gf | |
gf = GF(MODULUS) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried that for Field48 for example. And it fails with this assertion:
val = Field48(2**15)
assert 2**15 == val.as_unsigned()
I checked the val
property in Field
becomes 0, after computing self.gf(val)
. Any idea?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Side note: I don't think the initializer is performing any field operations, e.g. the computation of sq_norm_bound
, etc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well this was a pretty fun bug!
sage: GF(2^48.previous_prime())
Finite Field in z47 of size 2^47
sage: GF((2^48).previous_prime())
Finite Field of size 281474976710597
It turns out that 2^48.previous_prime()
is evaluated as 2^(48.previous_prime()) == 2^47
. In fact, GF(2^47)
is a finite field, just not a prime order finite field, which we need.
2**15
is represented as 0
in this field:
sage: f = GF(2^48.previous_prime())
sage: f(0)
0
sage: f(1)
1
sage: f(2)
0
sage: f(3)
1
sage: f(2**15)
0
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
GF(2^47)
is known as an extension field. Its elements are actually represented as polynomials. I think what sage is doing is interpreting the input as the coefficient of a degree-0 polynomial in the field.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
By the way, feel free to just not define gf
... that way the code fails noisily if we try to use it as a fully fledged field.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch, thanks! Not defining gf
will not let me instantiate a field element from an integer though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seemed to have changed the results too. It seems that for Field48 and above, we can just use a large alpha (e.g. 8.63), and for Field40, alpha is 1.90, num_wr_checks = 450, and num_wr_successes = 344.
Open thread: #81 (comment). Not sure why after computing |
poc/find_wr_params.sage
Outdated
ENCODED_SIZE = 6 | ||
|
||
# Operational parameters | ||
gf = Field64.gf |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well this was a pretty fun bug!
sage: GF(2^48.previous_prime())
Finite Field in z47 of size 2^47
sage: GF((2^48).previous_prime())
Finite Field of size 281474976710597
It turns out that 2^48.previous_prime()
is evaluated as 2^(48.previous_prime()) == 2^47
. In fact, GF(2^47)
is a finite field, just not a prime order finite field, which we need.
2**15
is represented as 0
in this field:
sage: f = GF(2^48.previous_prime())
sage: f(0)
0
sage: f(1)
1
sage: f(2)
0
sage: f(3)
1
sage: f(2**15)
0
poc/find_wr_params.sage
Outdated
ENCODED_SIZE = 6 | ||
|
||
# Operational parameters | ||
gf = Field64.gf |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
GF(2^47)
is known as an extension field. Its elements are actually represented as polynomials. I think what sage is doing is interpreting the input as the coefficient of a degree-0 polynomial in the field.
The improvements come as: - We now look for the smallest num_wr_successes that satisfies soundness, then searches for alpha (if possible) that can satisfy ZK. - Then combine with dimension to compute the number of proofs to satisfy the overall soundness.
a927069
to
d8d51e3
Compare
Squashed. |
The improvements come as:
Turns out with num_frac_bits = 24, neither Field56, nor Field48 can satisfy the field size requirement in wraparound checks.