Current Implementation
Currently, the DKG lagrange_at_zero() function computes:
λ_i = ∏_{j ∈ T, j ≠ i} (-j)/(i-j)
This is correct but naive O(t²) per resharing operation. For small committees it’s fine, but it becomes inefficient for larger committees or frequent resharing/refresh rounds.
Proposed Improvement
Switch to barycentric Lagrange interpolation:
- Compute barycentric weights once per set of participating nodes:
w_i = 1 / ∏_{j ≠ i} (i - j)
- Compute Lagrange coefficients at 0:
λ_i = (w_i / i) / Σ_{k ∈ T} (w_k / k)
This reduces repeated computation for multiple resharing operations.
Benefits
- More efficient for large committees (
t > 50) and frequent resharing.
- Coefficients can be cached per participating set.
- Mathematically equivalent to the current computation (same security properties).
- Aligns with practices in FROST, BLS threshold schemes, and other MPC implementations.
Suggested Implementation
- Add a
lagrange_at_zero_barycentric() function.
- Use
participating_ids to compute weights once.
- Use the weight for the current node to compute the reshared constant term:
let lambdas = lagrange_at_zero_barycentric(&participating_ids)?;
let index = participating_ids.iter().position(|id| *id == self.id)?;
let constant_term = lambdas[index] * old_share;
- Optional: cache computed weights for reuse.
Current Implementation
Currently, the DKG
lagrange_at_zero()function computes:This is correct but naive O(t²) per resharing operation. For small committees it’s fine, but it becomes inefficient for larger committees or frequent resharing/refresh rounds.
Proposed Improvement
Switch to barycentric Lagrange interpolation:
This reduces repeated computation for multiple resharing operations.
Benefits
t > 50) and frequent resharing.Suggested Implementation
lagrange_at_zero_barycentric()function.participating_idsto compute weights once.