Support caching preprocesses in FROST (#190)

* Remove the explicit included participants from FROST

Now, whoever submits preprocesses becomes the signing set. Better separates
preprocess from sign, at the cost of slightly more annoying integrations
(Monero needs to now independently lagrange/offset its key images).

* Support caching preprocesses

Closes https://github.com/serai-dex/serai/issues/40.

I *could* have added a serialization trait to Algorithm and written a ton of
data to disk, while requiring Algorithm implementors also accept such work.
Instead, I moved preprocess to a seeded RNG (Chacha20) which should be as
secure as the regular RNG. Rebuilding from cache simply loads the previously
used Chacha seed, making the Algorithm oblivious to the fact it's being
rebuilt from a cache. This removes any requirements for it to be modified
while guaranteeing equivalency.

This builds on the last commit which delayed determining the signing set till
post-preprocess acquisition. Unfortunately, that commit did force preprocess
from ThresholdView to ThresholdKeys which had visible effects on Monero.

Serai will actually need delayed set determination for #163, and overall,
it remains better, hence it's inclusion.

* Document FROST preprocess caching

* Update ethereum to new FROST

* Fix bug in Monero offset calculation and update processor
This commit is contained in:
Luke Parker
2022-12-08 19:04:35 -05:00
committed by GitHub
parent 873d27685a
commit af86b7a499
20 changed files with 339 additions and 162 deletions

View File

@@ -284,11 +284,13 @@ pub struct ThresholdKeys<C: Ciphersuite> {
/// View of keys passed to algorithm implementations.
#[derive(Clone, Zeroize)]
pub struct ThresholdView<C: Ciphersuite> {
offset: C::F,
group_key: C::G,
#[zeroize(skip)]
included: Vec<u16>,
secret_share: Zeroizing<C::F>,
#[zeroize(skip)]
original_verification_shares: HashMap<u16, C::G>,
#[zeroize(skip)]
verification_shares: HashMap<u16, C::G>,
}
@@ -347,10 +349,12 @@ impl<C: Ciphersuite> ThresholdKeys<C> {
let offset_verification_share = C::generator() * offset_share;
Ok(ThresholdView {
offset: self.offset.unwrap_or_else(C::F::zero),
group_key: self.group_key(),
secret_share: Zeroizing::new(
(lagrange::<C::F>(self.params().i, included) * self.secret_share().deref()) + offset_share,
),
original_verification_shares: self.verification_shares(),
verification_shares: self
.verification_shares()
.iter()
@@ -364,6 +368,10 @@ impl<C: Ciphersuite> ThresholdKeys<C> {
}
impl<C: Ciphersuite> ThresholdView<C> {
pub fn offset(&self) -> C::F {
self.offset
}
pub fn group_key(&self) -> C::G {
self.group_key
}
@@ -376,6 +384,10 @@ impl<C: Ciphersuite> ThresholdView<C> {
&self.secret_share
}
pub fn original_verification_share(&self, l: u16) -> C::G {
self.original_verification_shares[&l]
}
pub fn verification_share(&self, l: u16) -> C::G {
self.verification_shares[&l]
}