3.6.8 Simplify offset splitting

This wasn't done prior to be 'leaderless', as now the participant with the
lowest ID has an extra step, yet this is still trivial. There's also notable
performance benefits to not taking the previous dividing approach, which
performed an exp.
This commit is contained in:
Luke Parker 2023-03-01 01:06:13 -05:00
parent a42a84e1e8
commit c6284b85a4
No known key found for this signature in database
3 changed files with 23 additions and 21 deletions

View file

@ -401,31 +401,35 @@ impl<C: Ciphersuite> ThresholdKeys<C> {
self.core.serialize()
}
pub fn view(&self, included: &[Participant]) -> Result<ThresholdView<C>, DkgError<()>> {
pub fn view(&self, mut included: Vec<Participant>) -> Result<ThresholdView<C>, DkgError<()>> {
if (included.len() < self.params().t.into()) || (usize::from(self.params().n) < included.len())
{
Err(DkgError::InvalidSigningSet)?;
}
included.sort();
let offset_share = self.offset.unwrap_or_else(C::F::zero) *
C::F::from(included.len().try_into().unwrap()).invert().unwrap();
let offset_verification_share = C::generator() * offset_share;
let mut secret_share =
Zeroizing::new(lagrange::<C::F>(self.params().i, &included) * self.secret_share().deref());
let mut verification_shares = self.verification_shares();
for (i, share) in verification_shares.iter_mut() {
*share *= lagrange::<C::F>(*i, &included);
}
// The offset is included by adding it to the participant with the lowest ID
let offset = self.offset.unwrap_or_else(C::F::zero);
if included[0] == self.params().i() {
*secret_share += offset;
}
*verification_shares.get_mut(&included[0]).unwrap() += C::generator() * offset;
Ok(ThresholdView {
offset: self.offset.unwrap_or_else(C::F::zero),
offset,
group_key: self.group_key(),
secret_share: Zeroizing::new(
(lagrange::<C::F>(self.params().i, included) * self.secret_share().deref()) + offset_share,
),
secret_share,
original_verification_shares: self.verification_shares(),
verification_shares: self
.verification_shares()
.iter()
.map(|(l, share)| {
(*l, (*share * lagrange::<C::F>(*l, included)) + offset_verification_share)
})
.collect(),
included: included.to_vec(),
verification_shares,
included,
})
}
}

View file

@ -318,7 +318,7 @@ impl<C: Curve, A: Algorithm<C>> SignMachine<A::Signature> for AlgorithmSignMachi
}
}
let view = self.params.keys.view(&included).unwrap();
let view = self.params.keys.view(included.clone()).unwrap();
validate_map(&preprocesses, &included, multisig_params.i())?;
{

View file

@ -39,10 +39,8 @@ elements instead of `2n`.
Finally, to support additive offset signing schemes (accounts, stealth
addresses, randomization), it's possible to specify a scalar offset for keys.
The public key signed for is also offset by this value. During the signing
process, the offset is explicitly transcripted. Then, the offset is divided by
`p`, the amount of participating signers, and each signer adds it to their
post-interpolation key share. This maintains a leaderless protocol while still
being correct.
process, the offset is explicitly transcripted. Then, the offset is added to the
participant with the lowest ID.
# Caching