Files
nym/validator-api/src/coconut/dkg/controller.rs
T
Bogdan-Ștefan Neacşu 2db1bc8efa Feature/dkg publish vk (#1747)
* Save to disk coconut keypair

* Check verification keys of the other signers

* Post verification key to chain

* Add multisig propose/vote for vks

* Execute the proposal

* Parse announce address argument

* Gateway uses chain data

* Network requester uses chain data

* Native&socks5 clients use chain data

* Credential client signature uses chain data

* Remove redundant api endpoints

* Undo debugging logging

* Fix some tests

* Fix clippy

* Fix wasm client and contract test

* More contract clippy

* Update CHANGELOG

* Use a bigger expiry period then the testing one
2022-11-22 11:16:02 +02:00

134 lines
4.9 KiB
Rust

// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::coconut::dkg::client::DkgClient;
use crate::coconut::dkg::state::{ConsistentState, State};
use crate::coconut::dkg::verification_key::{
verification_key_finalization, verification_key_validation,
};
use crate::coconut::dkg::{
dealing::dealing_exchange, public_key::public_key_submission,
verification_key::verification_key_submission,
};
use crate::coconut::keypair::KeyPair as CoconutKeyPair;
use crate::{nymd_client, Config};
use anyhow::Result;
use coconut_dkg_common::types::EpochState;
use dkg::bte::keys::KeyPair as DkgKeyPair;
use rand::rngs::OsRng;
use rand::RngCore;
use std::path::PathBuf;
use std::time::Duration;
use task::ShutdownListener;
use tokio::time::interval;
use validator_client::nymd::SigningNymdClient;
pub(crate) fn init_keypair(config: &Config) -> Result<()> {
let mut rng = OsRng;
let dkg_params = dkg::bte::setup();
let kp = DkgKeyPair::new(&dkg_params, &mut rng);
pemstore::store_keypair(
&kp,
&pemstore::KeyPairPath::new(
config.decryption_key_path(),
config.public_key_with_proof_path(),
),
)?;
Ok(())
}
pub(crate) struct DkgController<R> {
dkg_client: DkgClient,
secret_key_path: PathBuf,
verification_key_path: PathBuf,
state: State,
rng: R,
polling_rate: Duration,
}
impl<R: RngCore + Clone> DkgController<R> {
pub(crate) async fn new(
config: &Config,
nymd_client: nymd_client::Client<SigningNymdClient>,
coconut_keypair: CoconutKeyPair,
rng: R,
) -> Result<Self> {
let dkg_keypair = pemstore::load_keypair(&pemstore::KeyPairPath::new(
config.decryption_key_path(),
config.public_key_with_proof_path(),
))?;
if let Ok(coconut_keypair_value) = pemstore::load_keypair(&pemstore::KeyPairPath::new(
config.secret_key_path(),
config.verification_key_path(),
)) {
coconut_keypair.set(coconut_keypair_value).await;
}
Ok(DkgController {
dkg_client: DkgClient::new(nymd_client),
secret_key_path: config.secret_key_path(),
verification_key_path: config.verification_key_path(),
state: State::new(config.get_announce_address(), dkg_keypair, coconut_keypair),
rng,
polling_rate: config.get_dkg_contract_polling_rate(),
})
}
async fn handle_epoch_state(&mut self) {
match self.dkg_client.get_current_epoch_state().await {
Err(e) => warn!("Could not get current epoch state {}", e),
Ok(epoch_state) => {
if let Err(e) = self.state.is_consistent(epoch_state).await {
error!(
"Epoch state is corrupted - {}, the process should be terminated",
e
);
}
let ret = match epoch_state {
EpochState::PublicKeySubmission => {
public_key_submission(&self.dkg_client, &mut self.state).await
}
EpochState::DealingExchange => {
dealing_exchange(&self.dkg_client, &mut self.state, self.rng.clone()).await
}
EpochState::VerificationKeySubmission => {
let keypair_path = pemstore::KeyPairPath::new(
self.secret_key_path.clone(),
self.verification_key_path.clone(),
);
verification_key_submission(
&self.dkg_client,
&mut self.state,
&keypair_path,
)
.await
}
EpochState::VerificationKeyValidation => {
verification_key_validation(&self.dkg_client, &mut self.state).await
}
EpochState::VerificationKeyFinalization => {
verification_key_finalization(&self.dkg_client, &mut self.state).await
}
// Just wait, in case we need to redo dkg at some point
EpochState::InProgress => Ok(()),
};
if let Err(e) = ret {
warn!("Could not handle this iteration for the epoch state: {}", e);
}
}
}
}
pub(crate) async fn run(mut self, mut shutdown: ShutdownListener) {
let mut interval = interval(self.polling_rate);
while !shutdown.is_shutdown() {
tokio::select! {
_ = interval.tick() => self.handle_epoch_state().await,
_ = shutdown.recv() => {
trace!("DkgController: Received shutdown");
}
}
}
}
}