Skip to content
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

Optimize lagrange coef computation #102

Open
survived opened this issue May 24, 2024 · 9 comments
Open

Optimize lagrange coef computation #102

survived opened this issue May 24, 2024 · 9 comments

Comments

@survived
Copy link
Contributor

survived commented May 24, 2024

When we do interpolation for VSS keys, we calculate lagrange coefficients (we do that in key share validation, in DKG and signing protocols). Each lagrange coef computation does a modular inversion which could be expensive. Recall that the formula for computing lagrange coef is:

$$\text{coef}(j, x, \vec x) = \frac{\prod_{m \ne j} x - \vec x_m}{\prod_{m \ne j} \vec x_j - \vec x_m}$$

(it's defined here)

Note that the denominator is independent of $x$ and that $\vec x$ is fixed at DKG. We can precompute in advance a table $T_{i,j} = (\vec x_i - \vec x_j)^{-1}$ for each $i < j$ (which will have size $\frac{n^2}{2}$), so we never have to do a modular inversion ever again when computing lagrange coefficient.

@maurges
Copy link
Contributor

maurges commented May 24, 2024

Good idea. I think we might rather put it to generic-ec

@maurges
Copy link
Contributor

maurges commented May 24, 2024

Looking at some usages, an interface that might work is fn lagrange_coefficients(x, xs, t) -> impl Iterator<Item = Scalar>

@survived
Copy link
Contributor Author

This is also a valid approach, tho here I'm suggesting to store additional data in the key share so we actually don't need to do a modular inversion. I'll open a separate issue in generic-ec

@survived
Copy link
Contributor Author

Opened LFDT-Lockness/generic-ec#39

@maurges
Copy link
Contributor

maurges commented May 24, 2024

I'm vary to increase our keyshare size. I think rather than that, when we fix the signer indexes in clusters, the xs will not change between key shares, so we can precompute denominators for a whole signer, not for a key.

@survived
Copy link
Contributor Author

We don't necessarily need to store that information on the disk, we can update the key share before invoking signing, for instance

@maurges
Copy link
Contributor

maurges commented May 24, 2024

Hm, but how is that better than using the optimized generic-ec function? I see we only create lagrange coefficients once per protocol. With fixed indexes that's a certain optimization though.

@survived
Copy link
Contributor Author

survived commented May 24, 2024

Usually, we do optimization only when we are explicitly asked to. E.g. when you generate aux data, you can ask it to optimize the aux data by calling Builder::precompute_multiexp_tables method. Otherwise, it's still possible to optimize the key share after aux gen is done by calling AuxInfo::precompute_multiexp_tables.

I was thinking about similar approach: DKG may or may not precompute a table for lagrange coefs. Then we'd add something like KeyShare::build_lagrange_table. So we can extract lagrange table before serializing, and put it back after deserializing.

Alternatively, lagrange table could be separated from key share completely and provided as an optional input to the protocol. I'm not sure which approach is nicer. Whoever gets to implement this optimization gotta examine all options and choose a better one :)

@survived
Copy link
Contributor Author

survived commented May 24, 2024

Oh I misunderstood your question...

Hm, but how is that better than using the optimized generic-ec function? I see we only create lagrange coefficients once per protocol. With fixed indexes that's a certain optimization though.

I was suggesting that we store lagrange table on disk, we don't necessarily need to store them within key share. As you noticed, in our use-case for every key share the table will be the same, so we can store that table in one place, and populate deserialized key shares with the table before invoking the protocol

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants