more completed key finalization
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use crate::coconut::dkg::key_finalization::KeyFinalizationError;
|
||||
use crate::coconut::error::CoconutError;
|
||||
use std::path::PathBuf;
|
||||
use thiserror::Error;
|
||||
@@ -56,7 +57,7 @@ pub enum DkgError {
|
||||
#[error("failed to finalize verification keys in the DKG contract: {source}")]
|
||||
VerificationKeyFinalizationFailure {
|
||||
#[source]
|
||||
source: CoconutError,
|
||||
source: KeyFinalizationError,
|
||||
},
|
||||
|
||||
#[error("failed to advance the DKG state: {source}")]
|
||||
|
||||
@@ -172,7 +172,7 @@ impl<R: RngCore + CryptoRng + Clone> DkgController<R> {
|
||||
) -> Result<(), DkgError> {
|
||||
debug!("DKG: verification key finalization (resharing: {resharing})");
|
||||
|
||||
self.verification_key_finalization(epoch_id, resharing)
|
||||
self.verification_key_finalization(epoch_id)
|
||||
.await
|
||||
.map_err(|source| DkgError::VerificationKeyFinalizationFailure { source })
|
||||
}
|
||||
|
||||
@@ -484,6 +484,7 @@ impl<R: RngCore + CryptoRng> DkgController<R> {
|
||||
// check if we have already generated the new keys and submitted verification proposal
|
||||
if key_generation_state.completed() {
|
||||
// TODO: ASSERT: we have a VALID key
|
||||
// TODO: ASSERT we have a valid proposal id
|
||||
|
||||
// the only way this could be a false positive is if the chain forked and blocks got reverted,
|
||||
// but I don't think we have to worry about that
|
||||
@@ -505,6 +506,7 @@ impl<R: RngCore + CryptoRng> DkgController<R> {
|
||||
.await?;
|
||||
if maybe_share.is_some() {
|
||||
todo!("finalize, we're done")
|
||||
// TODO: recover proposal id with some weird queries
|
||||
}
|
||||
|
||||
// ASSUMPTION:
|
||||
@@ -527,7 +529,8 @@ impl<R: RngCore + CryptoRng> DkgController<R> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
let proposal_id = self.submit_partial_verification_key(coconut_keypair.keys.verification_key(), resharing)
|
||||
let proposal_id = self
|
||||
.submit_partial_verification_key(coconut_keypair.keys.verification_key(), resharing)
|
||||
.await?;
|
||||
|
||||
self.state.set_coconut_keypair(coconut_keypair).await;
|
||||
@@ -1009,326 +1012,4 @@ pub(crate) mod tests {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[ignore] // expensive test
|
||||
async fn reshare_preserves_keys() {
|
||||
todo!()
|
||||
// let db = MockContractDb::new();
|
||||
// let mut clients_and_states = prepare_clients_and_states_with_finalization(&db).await;
|
||||
// for controller in clients_and_states.iter_mut() {
|
||||
// controller.state.set_was_in_progress();
|
||||
// }
|
||||
//
|
||||
// let mut vks = vec![];
|
||||
// let mut indices = vec![];
|
||||
// for controller in clients_and_states.iter() {
|
||||
// let vk = controller
|
||||
// .state
|
||||
// .coconut_keypair()
|
||||
// .await
|
||||
// .as_ref()
|
||||
// .unwrap()
|
||||
// .keys
|
||||
// .verification_key()
|
||||
// .clone();
|
||||
// let index = controller.state.node_index().unwrap();
|
||||
// vks.push(vk);
|
||||
// indices.push(index);
|
||||
// }
|
||||
// let initial_master_vk = aggregate_verification_keys(&vks, Some(&indices)).unwrap();
|
||||
//
|
||||
// let new_dkg_client = DkgClient::new(
|
||||
// DummyClient::new(
|
||||
// AccountId::from_str("n1sqkxzh7nl6kgndr4ew9795t2nkwmd8tpql67q7").unwrap(),
|
||||
// )
|
||||
// .with_dealer_details(&db.dealer_details_db)
|
||||
// .with_dealings(&db.dealings_db)
|
||||
// .with_proposal_db(&db.proposal_db)
|
||||
// .with_verification_share(&db.verification_share_db)
|
||||
// .with_threshold(&db.threshold_db)
|
||||
// .with_initial_dealers_db(&db.initial_dealers_db),
|
||||
// );
|
||||
// let keypair = DkgKeyPair::new(dkg::params(), OsRng);
|
||||
// let identity_keypair = identity::KeyPair::new(&mut thread_rng());
|
||||
// let state = State::new(
|
||||
// PathBuf::default(),
|
||||
// PersistentState::default(),
|
||||
// Url::parse("localhost:8000").unwrap(),
|
||||
// keypair,
|
||||
// *identity_keypair.public_key(),
|
||||
// KeyPair::new(),
|
||||
// );
|
||||
//
|
||||
// for (_, active) in db.dealer_details_db.write().unwrap().values_mut() {
|
||||
// *active = false;
|
||||
// }
|
||||
//
|
||||
// *db.dealings_db.write().unwrap() = Default::default();
|
||||
// *db.verification_share_db.write().unwrap() = Default::default();
|
||||
// let mut initial_dealers = vec![];
|
||||
// for controller in clients_and_states.iter() {
|
||||
// let client_address =
|
||||
// Addr::unchecked(controller.dkg_client.get_address().await.as_ref());
|
||||
// initial_dealers.push(client_address);
|
||||
// }
|
||||
// *db.initial_dealers_db.write().unwrap() = Some(InitialReplacementData {
|
||||
// initial_dealers,
|
||||
// initial_height: 1,
|
||||
// });
|
||||
// *clients_and_states.first_mut().unwrap() = DkgController::test_mock(new_dkg_client, state);
|
||||
//
|
||||
// for controller in clients_and_states.iter_mut() {
|
||||
// controller.public_key_submission(0, true).await.unwrap();
|
||||
// controller.dealing_exchange(0, true).await.unwrap();
|
||||
// }
|
||||
//
|
||||
// for controller in clients_and_states.iter_mut() {
|
||||
// let random_file: usize = OsRng.gen();
|
||||
// let keypath = temp_dir().join(format!("coconut{}.pem", random_file));
|
||||
// verification_key_submission(
|
||||
// &controller.dkg_client,
|
||||
// &mut controller.state,
|
||||
// 0,
|
||||
// &keypath,
|
||||
// true,
|
||||
// )
|
||||
// .await
|
||||
// .unwrap();
|
||||
// std::fs::remove_file(keypath).unwrap();
|
||||
// }
|
||||
// for controller in clients_and_states.iter_mut() {
|
||||
// verification_key_validation(&controller.dkg_client, &mut controller.state, true)
|
||||
// .await
|
||||
// .unwrap();
|
||||
// }
|
||||
// for controller in clients_and_states.iter_mut() {
|
||||
// verification_key_finalization(&controller.dkg_client, &mut controller.state, true)
|
||||
// .await
|
||||
// .unwrap();
|
||||
// }
|
||||
// assert!(db
|
||||
// .proposal_db
|
||||
// .read()
|
||||
// .unwrap()
|
||||
// .values()
|
||||
// .all(|proposal| { proposal.status == Status::Executed }));
|
||||
//
|
||||
// let mut vks = vec![];
|
||||
// let mut indices = vec![];
|
||||
// for controller in clients_and_states.iter() {
|
||||
// let vk = controller
|
||||
// .state
|
||||
// .coconut_keypair()
|
||||
// .await
|
||||
// .as_ref()
|
||||
// .unwrap()
|
||||
// .keys
|
||||
// .verification_key()
|
||||
// .clone();
|
||||
// let index = controller.state.node_index().unwrap();
|
||||
// vks.push(vk);
|
||||
// indices.push(index);
|
||||
// }
|
||||
// let reshared_master_vk = aggregate_verification_keys(&vks, Some(&indices)).unwrap();
|
||||
// assert_eq!(initial_master_vk, reshared_master_vk);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[ignore] // expensive test
|
||||
async fn reshare_after_reset() {
|
||||
todo!()
|
||||
// let db = MockContractDb::new();
|
||||
// let mut clients_and_states = prepare_clients_and_states_with_finalization(&db).await;
|
||||
// for controller in clients_and_states.iter_mut() {
|
||||
// controller.state.set_was_in_progress();
|
||||
// }
|
||||
//
|
||||
// let new_dkg_client = DkgClient::new(
|
||||
// DummyClient::new(
|
||||
// AccountId::from_str("n1vxkywf9g4cg0k2dehanzwzz64jw782qm0kuynf").unwrap(),
|
||||
// )
|
||||
// .with_dealer_details(&db.dealer_details_db)
|
||||
// .with_dealings(&db.dealings_db)
|
||||
// .with_proposal_db(&db.proposal_db)
|
||||
// .with_verification_share(&db.verification_share_db)
|
||||
// .with_threshold(&db.threshold_db)
|
||||
// .with_initial_dealers_db(&db.initial_dealers_db),
|
||||
// );
|
||||
// let keypair = DkgKeyPair::new(dkg::params(), OsRng);
|
||||
// let identity_keypair = identity::KeyPair::new(&mut thread_rng());
|
||||
// let state = State::new(
|
||||
// PathBuf::default(),
|
||||
// PersistentState::default(),
|
||||
// Url::parse("localhost:8000").unwrap(),
|
||||
// keypair,
|
||||
// *identity_keypair.public_key(),
|
||||
// KeyPair::new(),
|
||||
// );
|
||||
// let new_dkg_client2 = DkgClient::new(
|
||||
// DummyClient::new(
|
||||
// AccountId::from_str("n1sqkxzh7nl6kgndr4ew9795t2nkwmd8tpql67q7").unwrap(),
|
||||
// )
|
||||
// .with_dealer_details(&db.dealer_details_db)
|
||||
// .with_dealings(&db.dealings_db)
|
||||
// .with_proposal_db(&db.proposal_db)
|
||||
// .with_verification_share(&db.verification_share_db)
|
||||
// .with_threshold(&db.threshold_db)
|
||||
// .with_initial_dealers_db(&db.initial_dealers_db),
|
||||
// );
|
||||
// let keypair = DkgKeyPair::new(dkg::params(), OsRng);
|
||||
// let identity_keypair = identity::KeyPair::new(&mut thread_rng());
|
||||
// let state2 = State::new(
|
||||
// PathBuf::default(),
|
||||
// PersistentState::default(),
|
||||
// Url::parse("localhost:8000").unwrap(),
|
||||
// keypair,
|
||||
// *identity_keypair.public_key(),
|
||||
// KeyPair::new(),
|
||||
// );
|
||||
//
|
||||
// for (_, active) in db.dealer_details_db.write().unwrap().values_mut() {
|
||||
// *active = false;
|
||||
// }
|
||||
//
|
||||
// *db.dealings_db.write().unwrap() = Default::default();
|
||||
// *db.verification_share_db.write().unwrap() = Default::default();
|
||||
// clients_and_states.pop().unwrap();
|
||||
// let controller2 = clients_and_states.pop().unwrap();
|
||||
// clients_and_states.push(DkgController::test_mock(new_dkg_client, state));
|
||||
// clients_and_states.push(DkgController::test_mock(new_dkg_client2, state2));
|
||||
//
|
||||
// // DKG in reset mode
|
||||
// for controller in clients_and_states.iter_mut() {
|
||||
// controller.public_key_submission(0, false).await.unwrap();
|
||||
// }
|
||||
// for controller in clients_and_states.iter_mut() {
|
||||
// controller.dealing_exchange(0, false).await.unwrap();
|
||||
// }
|
||||
// for controller in clients_and_states.iter_mut() {
|
||||
// let random_file: usize = OsRng.gen();
|
||||
// let keypath = temp_dir().join(format!("coconut{}.pem", random_file));
|
||||
// verification_key_submission(
|
||||
// &controller.dkg_client,
|
||||
// &mut controller.state,
|
||||
// 0,
|
||||
// &keypath,
|
||||
// false,
|
||||
// )
|
||||
// .await
|
||||
// .unwrap();
|
||||
// std::fs::remove_file(keypath).unwrap();
|
||||
// }
|
||||
// for controller in clients_and_states.iter_mut() {
|
||||
// verification_key_validation(&controller.dkg_client, &mut controller.state, false)
|
||||
// .await
|
||||
// .unwrap();
|
||||
// }
|
||||
// for controller in clients_and_states.iter_mut() {
|
||||
// verification_key_finalization(&controller.dkg_client, &mut controller.state, false)
|
||||
// .await
|
||||
// .unwrap();
|
||||
// }
|
||||
// assert!(db
|
||||
// .proposal_db
|
||||
// .read()
|
||||
// .unwrap()
|
||||
// .values()
|
||||
// .all(|proposal| { proposal.status == Status::Executed }));
|
||||
// for controller in clients_and_states.iter_mut() {
|
||||
// controller.state.set_was_in_progress();
|
||||
// }
|
||||
//
|
||||
// // DKG in reshare mode
|
||||
// let mut vks = vec![];
|
||||
// let mut indices = vec![];
|
||||
// for controller in clients_and_states.iter() {
|
||||
// let vk = controller
|
||||
// .state
|
||||
// .coconut_keypair()
|
||||
// .await
|
||||
// .as_ref()
|
||||
// .unwrap()
|
||||
// .keys
|
||||
// .verification_key()
|
||||
// .clone();
|
||||
// let index = controller.state.node_index().unwrap();
|
||||
// vks.push(vk);
|
||||
// indices.push(index);
|
||||
// }
|
||||
// let initial_master_vk = aggregate_verification_keys(&vks, Some(&indices)).unwrap();
|
||||
//
|
||||
// for (_, active) in db.dealer_details_db.write().unwrap().values_mut() {
|
||||
// *active = false;
|
||||
// }
|
||||
// *db.dealings_db.write().unwrap() = Default::default();
|
||||
// *db.verification_share_db.write().unwrap() = Default::default();
|
||||
// let mut initial_dealers = vec![];
|
||||
// for controller in clients_and_states.iter() {
|
||||
// let client_address =
|
||||
// Addr::unchecked(controller.dkg_client.get_address().await.as_ref());
|
||||
// initial_dealers.push(client_address);
|
||||
// }
|
||||
// *db.initial_dealers_db.write().unwrap() = Some(InitialReplacementData {
|
||||
// initial_dealers,
|
||||
// initial_height: 1,
|
||||
// });
|
||||
// *clients_and_states.last_mut().unwrap() = controller2;
|
||||
//
|
||||
// for controller in clients_and_states.iter_mut() {
|
||||
// controller.public_key_submission(0, true).await.unwrap();
|
||||
// controller.dealing_exchange(0, true).await.unwrap();
|
||||
// }
|
||||
//
|
||||
// for controller in clients_and_states.iter_mut() {
|
||||
// let random_file: usize = OsRng.gen();
|
||||
// let keypath = temp_dir().join(format!("coconut{}.pem", random_file));
|
||||
// verification_key_submission(
|
||||
// &controller.dkg_client,
|
||||
// &mut controller.state,
|
||||
// 0,
|
||||
// &keypath,
|
||||
// true,
|
||||
// )
|
||||
// .await
|
||||
// .unwrap();
|
||||
// std::fs::remove_file(keypath).unwrap();
|
||||
// }
|
||||
//
|
||||
// for controller in clients_and_states.iter_mut() {
|
||||
// verification_key_validation(&controller.dkg_client, &mut controller.state, true)
|
||||
// .await
|
||||
// .unwrap();
|
||||
// }
|
||||
// for controller in clients_and_states.iter_mut() {
|
||||
// verification_key_finalization(&controller.dkg_client, &mut controller.state, true)
|
||||
// .await
|
||||
// .unwrap();
|
||||
// }
|
||||
// // assert!(db
|
||||
// // .proposal_db
|
||||
// // .read()
|
||||
// // .unwrap()
|
||||
// // .values()
|
||||
// // .all(|proposal| { proposal.status == Status::Executed }));
|
||||
//
|
||||
// let mut vks = vec![];
|
||||
// let mut indices = vec![];
|
||||
// for controller in clients_and_states.iter() {
|
||||
// let vk = controller
|
||||
// .state
|
||||
// .coconut_keypair()
|
||||
// .await
|
||||
// .as_ref()
|
||||
// .unwrap()
|
||||
// .keys
|
||||
// .verification_key()
|
||||
// .clone();
|
||||
// let index = controller.state.node_index().unwrap();
|
||||
// vks.push(vk);
|
||||
// indices.push(index);
|
||||
// }
|
||||
// let reshared_master_vk = aggregate_verification_keys(&vks, Some(&indices)).unwrap();
|
||||
// assert_eq!(initial_master_vk, reshared_master_vk);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,20 +1,33 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use crate::coconut::dkg::client::DkgClient;
|
||||
use crate::coconut::dkg::controller::DkgController;
|
||||
use crate::coconut::dkg::state::{ConsistentState, State};
|
||||
use crate::coconut::error::CoconutError;
|
||||
use cw3::Status;
|
||||
use nym_coconut_dkg_common::types::EpochId;
|
||||
use rand::{CryptoRng, RngCore};
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum KeyFinalizationError {
|
||||
#[error(transparent)]
|
||||
CoconutError(#[from] CoconutError),
|
||||
|
||||
#[error("our proposal for key verification is still open (or is pending) (proposal id: {proposal_id}) ")]
|
||||
UnresolvedProposal { proposal_id: u64 },
|
||||
|
||||
#[error("our proposal for key verification has been rejected (proposal id: {proposal_id})")]
|
||||
RejectedProposal { proposal_id: u64 },
|
||||
|
||||
#[error("can't complete key finalization without key validation")]
|
||||
IncompleteKeyValidation,
|
||||
}
|
||||
|
||||
impl<R: RngCore + CryptoRng> DkgController<R> {
|
||||
pub(crate) async fn verification_key_finalization(
|
||||
&mut self,
|
||||
epoch_id: EpochId,
|
||||
_resharing: bool,
|
||||
) -> Result<(), CoconutError> {
|
||||
) -> Result<(), KeyFinalizationError> {
|
||||
let key_finalization_state = self.state.key_finalization_state(epoch_id)?;
|
||||
|
||||
// check if we have already executed our own proposal
|
||||
@@ -25,6 +38,10 @@ impl<R: RngCore + CryptoRng> DkgController<R> {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if !self.state.key_validation_state(epoch_id)?.completed {
|
||||
return Err(KeyFinalizationError::IncompleteKeyValidation);
|
||||
}
|
||||
|
||||
let proposal_id = self.state.proposal_id(epoch_id)?;
|
||||
|
||||
// check whether our key has already been verified with executed proposal,
|
||||
@@ -32,34 +49,42 @@ impl<R: RngCore + CryptoRng> DkgController<R> {
|
||||
// or by another party
|
||||
let status = self.dkg_client.get_proposal_status(proposal_id).await?;
|
||||
match status {
|
||||
// if the proposal hasn't been resolved, there's not much we can do but wait and pray
|
||||
Status::Pending | Status::Open => {
|
||||
// 'theoretically' it's possible that more votes are going to come in, but it's very unlikely
|
||||
warn!("our proposal ({proposal_id}) still hasn't received enough votes to get accepted");
|
||||
todo!();
|
||||
return Err(KeyFinalizationError::UnresolvedProposal { proposal_id });
|
||||
}
|
||||
// if the proposal has been rejected, there's nothing we can do, we failed the DKG
|
||||
Status::Rejected => {
|
||||
// TODO: technically there's nothing enforcing this...
|
||||
// technically there's nothing enforcing this, so as long as our keys have been properly generated
|
||||
// (even though they've been rejected by other parties), they could still issue [cryptographically] valid credentials
|
||||
error!("our key verification proposal ({proposal_id}) has been rejected - we can't use our derived keys!");
|
||||
todo!()
|
||||
self.state.key_finalization_state_mut(epoch_id)?.completed = true;
|
||||
return Err(KeyFinalizationError::RejectedProposal { proposal_id });
|
||||
}
|
||||
// if the proposal has passed, execute it to finalize our key
|
||||
Status::Passed => {
|
||||
self.dkg_client
|
||||
.execute_verification_key_share(proposal_id)
|
||||
.await?;
|
||||
}
|
||||
// if they proposal has already been executed, we're done!
|
||||
Status::Executed => {
|
||||
// generally each dealer is responsible for executing its own proposals,
|
||||
// but technically there's nothing preventing other dealers from executing them
|
||||
debug!("our dkg proposal has already been executed");
|
||||
}
|
||||
}
|
||||
|
||||
self.state.key_finalization_state_mut(epoch_id)?.completed = true;
|
||||
self.state.validate_coconut_keypair();
|
||||
info!("DKG: Finalized own verification key on chain");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
// each dealer is responsible for executing its own proposals
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
@@ -84,7 +109,7 @@ mod tests {
|
||||
validate_keys(&mut controllers, false).await;
|
||||
|
||||
for controller in controllers.iter_mut() {
|
||||
let res = controller.verification_key_finalization(epoch, false).await;
|
||||
let res = controller.verification_key_finalization(epoch).await;
|
||||
assert!(res.is_ok());
|
||||
|
||||
assert!(controller.state.key_finalization_state(epoch)?.completed);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||
// Copyright 2022-2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use std::sync::OnceLock;
|
||||
@@ -13,7 +13,334 @@ pub(crate) mod complaints;
|
||||
pub(crate) mod controller;
|
||||
pub(crate) mod dealing;
|
||||
pub(crate) mod key_derivation;
|
||||
mod key_finalization;
|
||||
mod key_validation;
|
||||
pub(crate) mod key_finalization;
|
||||
pub(crate) mod key_validation;
|
||||
pub(crate) mod public_key;
|
||||
pub(crate) mod state;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[tokio::test]
|
||||
#[ignore] // expensive test
|
||||
async fn reshare_preserves_keys() {
|
||||
todo!()
|
||||
// let db = MockContractDb::new();
|
||||
// let mut clients_and_states = prepare_clients_and_states_with_finalization(&db).await;
|
||||
// for controller in clients_and_states.iter_mut() {
|
||||
// controller.state.set_was_in_progress();
|
||||
// }
|
||||
//
|
||||
// let mut vks = vec![];
|
||||
// let mut indices = vec![];
|
||||
// for controller in clients_and_states.iter() {
|
||||
// let vk = controller
|
||||
// .state
|
||||
// .coconut_keypair()
|
||||
// .await
|
||||
// .as_ref()
|
||||
// .unwrap()
|
||||
// .keys
|
||||
// .verification_key()
|
||||
// .clone();
|
||||
// let index = controller.state.node_index().unwrap();
|
||||
// vks.push(vk);
|
||||
// indices.push(index);
|
||||
// }
|
||||
// let initial_master_vk = aggregate_verification_keys(&vks, Some(&indices)).unwrap();
|
||||
//
|
||||
// let new_dkg_client = DkgClient::new(
|
||||
// DummyClient::new(
|
||||
// AccountId::from_str("n1sqkxzh7nl6kgndr4ew9795t2nkwmd8tpql67q7").unwrap(),
|
||||
// )
|
||||
// .with_dealer_details(&db.dealer_details_db)
|
||||
// .with_dealings(&db.dealings_db)
|
||||
// .with_proposal_db(&db.proposal_db)
|
||||
// .with_verification_share(&db.verification_share_db)
|
||||
// .with_threshold(&db.threshold_db)
|
||||
// .with_initial_dealers_db(&db.initial_dealers_db),
|
||||
// );
|
||||
// let keypair = DkgKeyPair::new(dkg::params(), OsRng);
|
||||
// let identity_keypair = identity::KeyPair::new(&mut thread_rng());
|
||||
// let state = State::new(
|
||||
// PathBuf::default(),
|
||||
// PersistentState::default(),
|
||||
// Url::parse("localhost:8000").unwrap(),
|
||||
// keypair,
|
||||
// *identity_keypair.public_key(),
|
||||
// KeyPair::new(),
|
||||
// );
|
||||
//
|
||||
// for (_, active) in db.dealer_details_db.write().unwrap().values_mut() {
|
||||
// *active = false;
|
||||
// }
|
||||
//
|
||||
// *db.dealings_db.write().unwrap() = Default::default();
|
||||
// *db.verification_share_db.write().unwrap() = Default::default();
|
||||
// let mut initial_dealers = vec![];
|
||||
// for controller in clients_and_states.iter() {
|
||||
// let client_address =
|
||||
// Addr::unchecked(controller.dkg_client.get_address().await.as_ref());
|
||||
// initial_dealers.push(client_address);
|
||||
// }
|
||||
// *db.initial_dealers_db.write().unwrap() = Some(InitialReplacementData {
|
||||
// initial_dealers,
|
||||
// initial_height: 1,
|
||||
// });
|
||||
// *clients_and_states.first_mut().unwrap() = DkgController::test_mock(new_dkg_client, state);
|
||||
//
|
||||
// for controller in clients_and_states.iter_mut() {
|
||||
// controller.public_key_submission(0, true).await.unwrap();
|
||||
// controller.dealing_exchange(0, true).await.unwrap();
|
||||
// }
|
||||
//
|
||||
// for controller in clients_and_states.iter_mut() {
|
||||
// let random_file: usize = OsRng.gen();
|
||||
// let keypath = temp_dir().join(format!("coconut{}.pem", random_file));
|
||||
// verification_key_submission(
|
||||
// &controller.dkg_client,
|
||||
// &mut controller.state,
|
||||
// 0,
|
||||
// &keypath,
|
||||
// true,
|
||||
// )
|
||||
// .await
|
||||
// .unwrap();
|
||||
// std::fs::remove_file(keypath).unwrap();
|
||||
// }
|
||||
// for controller in clients_and_states.iter_mut() {
|
||||
// verification_key_validation(&controller.dkg_client, &mut controller.state, true)
|
||||
// .await
|
||||
// .unwrap();
|
||||
// }
|
||||
// for controller in clients_and_states.iter_mut() {
|
||||
// verification_key_finalization(&controller.dkg_client, &mut controller.state, true)
|
||||
// .await
|
||||
// .unwrap();
|
||||
// }
|
||||
// assert!(db
|
||||
// .proposal_db
|
||||
// .read()
|
||||
// .unwrap()
|
||||
// .values()
|
||||
// .all(|proposal| { proposal.status == Status::Executed }));
|
||||
//
|
||||
// let mut vks = vec![];
|
||||
// let mut indices = vec![];
|
||||
// for controller in clients_and_states.iter() {
|
||||
// let vk = controller
|
||||
// .state
|
||||
// .coconut_keypair()
|
||||
// .await
|
||||
// .as_ref()
|
||||
// .unwrap()
|
||||
// .keys
|
||||
// .verification_key()
|
||||
// .clone();
|
||||
// let index = controller.state.node_index().unwrap();
|
||||
// vks.push(vk);
|
||||
// indices.push(index);
|
||||
// }
|
||||
// let reshared_master_vk = aggregate_verification_keys(&vks, Some(&indices)).unwrap();
|
||||
// assert_eq!(initial_master_vk, reshared_master_vk);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[ignore] // expensive test
|
||||
async fn reshare_after_reset() {
|
||||
todo!()
|
||||
// let db = MockContractDb::new();
|
||||
// let mut clients_and_states = prepare_clients_and_states_with_finalization(&db).await;
|
||||
// for controller in clients_and_states.iter_mut() {
|
||||
// controller.state.set_was_in_progress();
|
||||
// }
|
||||
//
|
||||
// let new_dkg_client = DkgClient::new(
|
||||
// DummyClient::new(
|
||||
// AccountId::from_str("n1vxkywf9g4cg0k2dehanzwzz64jw782qm0kuynf").unwrap(),
|
||||
// )
|
||||
// .with_dealer_details(&db.dealer_details_db)
|
||||
// .with_dealings(&db.dealings_db)
|
||||
// .with_proposal_db(&db.proposal_db)
|
||||
// .with_verification_share(&db.verification_share_db)
|
||||
// .with_threshold(&db.threshold_db)
|
||||
// .with_initial_dealers_db(&db.initial_dealers_db),
|
||||
// );
|
||||
// let keypair = DkgKeyPair::new(dkg::params(), OsRng);
|
||||
// let identity_keypair = identity::KeyPair::new(&mut thread_rng());
|
||||
// let state = State::new(
|
||||
// PathBuf::default(),
|
||||
// PersistentState::default(),
|
||||
// Url::parse("localhost:8000").unwrap(),
|
||||
// keypair,
|
||||
// *identity_keypair.public_key(),
|
||||
// KeyPair::new(),
|
||||
// );
|
||||
// let new_dkg_client2 = DkgClient::new(
|
||||
// DummyClient::new(
|
||||
// AccountId::from_str("n1sqkxzh7nl6kgndr4ew9795t2nkwmd8tpql67q7").unwrap(),
|
||||
// )
|
||||
// .with_dealer_details(&db.dealer_details_db)
|
||||
// .with_dealings(&db.dealings_db)
|
||||
// .with_proposal_db(&db.proposal_db)
|
||||
// .with_verification_share(&db.verification_share_db)
|
||||
// .with_threshold(&db.threshold_db)
|
||||
// .with_initial_dealers_db(&db.initial_dealers_db),
|
||||
// );
|
||||
// let keypair = DkgKeyPair::new(dkg::params(), OsRng);
|
||||
// let identity_keypair = identity::KeyPair::new(&mut thread_rng());
|
||||
// let state2 = State::new(
|
||||
// PathBuf::default(),
|
||||
// PersistentState::default(),
|
||||
// Url::parse("localhost:8000").unwrap(),
|
||||
// keypair,
|
||||
// *identity_keypair.public_key(),
|
||||
// KeyPair::new(),
|
||||
// );
|
||||
//
|
||||
// for (_, active) in db.dealer_details_db.write().unwrap().values_mut() {
|
||||
// *active = false;
|
||||
// }
|
||||
//
|
||||
// *db.dealings_db.write().unwrap() = Default::default();
|
||||
// *db.verification_share_db.write().unwrap() = Default::default();
|
||||
// clients_and_states.pop().unwrap();
|
||||
// let controller2 = clients_and_states.pop().unwrap();
|
||||
// clients_and_states.push(DkgController::test_mock(new_dkg_client, state));
|
||||
// clients_and_states.push(DkgController::test_mock(new_dkg_client2, state2));
|
||||
//
|
||||
// // DKG in reset mode
|
||||
// for controller in clients_and_states.iter_mut() {
|
||||
// controller.public_key_submission(0, false).await.unwrap();
|
||||
// }
|
||||
// for controller in clients_and_states.iter_mut() {
|
||||
// controller.dealing_exchange(0, false).await.unwrap();
|
||||
// }
|
||||
// for controller in clients_and_states.iter_mut() {
|
||||
// let random_file: usize = OsRng.gen();
|
||||
// let keypath = temp_dir().join(format!("coconut{}.pem", random_file));
|
||||
// verification_key_submission(
|
||||
// &controller.dkg_client,
|
||||
// &mut controller.state,
|
||||
// 0,
|
||||
// &keypath,
|
||||
// false,
|
||||
// )
|
||||
// .await
|
||||
// .unwrap();
|
||||
// std::fs::remove_file(keypath).unwrap();
|
||||
// }
|
||||
// for controller in clients_and_states.iter_mut() {
|
||||
// verification_key_validation(&controller.dkg_client, &mut controller.state, false)
|
||||
// .await
|
||||
// .unwrap();
|
||||
// }
|
||||
// for controller in clients_and_states.iter_mut() {
|
||||
// verification_key_finalization(&controller.dkg_client, &mut controller.state, false)
|
||||
// .await
|
||||
// .unwrap();
|
||||
// }
|
||||
// assert!(db
|
||||
// .proposal_db
|
||||
// .read()
|
||||
// .unwrap()
|
||||
// .values()
|
||||
// .all(|proposal| { proposal.status == Status::Executed }));
|
||||
// for controller in clients_and_states.iter_mut() {
|
||||
// controller.state.set_was_in_progress();
|
||||
// }
|
||||
//
|
||||
// // DKG in reshare mode
|
||||
// let mut vks = vec![];
|
||||
// let mut indices = vec![];
|
||||
// for controller in clients_and_states.iter() {
|
||||
// let vk = controller
|
||||
// .state
|
||||
// .coconut_keypair()
|
||||
// .await
|
||||
// .as_ref()
|
||||
// .unwrap()
|
||||
// .keys
|
||||
// .verification_key()
|
||||
// .clone();
|
||||
// let index = controller.state.node_index().unwrap();
|
||||
// vks.push(vk);
|
||||
// indices.push(index);
|
||||
// }
|
||||
// let initial_master_vk = aggregate_verification_keys(&vks, Some(&indices)).unwrap();
|
||||
//
|
||||
// for (_, active) in db.dealer_details_db.write().unwrap().values_mut() {
|
||||
// *active = false;
|
||||
// }
|
||||
// *db.dealings_db.write().unwrap() = Default::default();
|
||||
// *db.verification_share_db.write().unwrap() = Default::default();
|
||||
// let mut initial_dealers = vec![];
|
||||
// for controller in clients_and_states.iter() {
|
||||
// let client_address =
|
||||
// Addr::unchecked(controller.dkg_client.get_address().await.as_ref());
|
||||
// initial_dealers.push(client_address);
|
||||
// }
|
||||
// *db.initial_dealers_db.write().unwrap() = Some(InitialReplacementData {
|
||||
// initial_dealers,
|
||||
// initial_height: 1,
|
||||
// });
|
||||
// *clients_and_states.last_mut().unwrap() = controller2;
|
||||
//
|
||||
// for controller in clients_and_states.iter_mut() {
|
||||
// controller.public_key_submission(0, true).await.unwrap();
|
||||
// controller.dealing_exchange(0, true).await.unwrap();
|
||||
// }
|
||||
//
|
||||
// for controller in clients_and_states.iter_mut() {
|
||||
// let random_file: usize = OsRng.gen();
|
||||
// let keypath = temp_dir().join(format!("coconut{}.pem", random_file));
|
||||
// verification_key_submission(
|
||||
// &controller.dkg_client,
|
||||
// &mut controller.state,
|
||||
// 0,
|
||||
// &keypath,
|
||||
// true,
|
||||
// )
|
||||
// .await
|
||||
// .unwrap();
|
||||
// std::fs::remove_file(keypath).unwrap();
|
||||
// }
|
||||
//
|
||||
// for controller in clients_and_states.iter_mut() {
|
||||
// verification_key_validation(&controller.dkg_client, &mut controller.state, true)
|
||||
// .await
|
||||
// .unwrap();
|
||||
// }
|
||||
// for controller in clients_and_states.iter_mut() {
|
||||
// verification_key_finalization(&controller.dkg_client, &mut controller.state, true)
|
||||
// .await
|
||||
// .unwrap();
|
||||
// }
|
||||
// // assert!(db
|
||||
// // .proposal_db
|
||||
// // .read()
|
||||
// // .unwrap()
|
||||
// // .values()
|
||||
// // .all(|proposal| { proposal.status == Status::Executed }));
|
||||
//
|
||||
// let mut vks = vec![];
|
||||
// let mut indices = vec![];
|
||||
// for controller in clients_and_states.iter() {
|
||||
// let vk = controller
|
||||
// .state
|
||||
// .coconut_keypair()
|
||||
// .await
|
||||
// .as_ref()
|
||||
// .unwrap()
|
||||
// .keys
|
||||
// .verification_key()
|
||||
// .clone();
|
||||
// let index = controller.state.node_index().unwrap();
|
||||
// vks.push(vk);
|
||||
// indices.push(index);
|
||||
// }
|
||||
// let reshared_master_vk = aggregate_verification_keys(&vks, Some(&indices)).unwrap();
|
||||
// assert_eq!(initial_master_vk, reshared_master_vk);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,8 @@ use crate::coconut::dkg::complaints::ComplaintReason;
|
||||
use crate::coconut::dkg::controller::keys::archive_coconut_keypair;
|
||||
use crate::coconut::dkg::state::dealing_exchange::DealingExchangeState;
|
||||
use crate::coconut::dkg::state::key_derivation::KeyDerivationState;
|
||||
use crate::coconut::dkg::state::key_finalization::FinalizationState;
|
||||
use crate::coconut::dkg::state::key_validation::ValidationState;
|
||||
use crate::coconut::dkg::state::registration::RegistrationState;
|
||||
use crate::coconut::error::CoconutError;
|
||||
use crate::coconut::keys::{KeyPair as CoconutKeyPair, KeyPairWithEpoch};
|
||||
@@ -26,8 +28,6 @@ use std::path::{Path, PathBuf};
|
||||
use time::OffsetDateTime;
|
||||
use tokio::sync::RwLockReadGuard;
|
||||
use url::Url;
|
||||
use crate::coconut::dkg::state::key_finalization::FinalizationState;
|
||||
use crate::coconut::dkg::state::key_validation::ValidationState;
|
||||
|
||||
mod dealing_exchange;
|
||||
mod key_derivation;
|
||||
@@ -246,13 +246,13 @@ impl PersistentState {
|
||||
#[derive(Default)]
|
||||
pub(crate) struct DkgState {
|
||||
pub(crate) registration: RegistrationState,
|
||||
|
||||
|
||||
pub(crate) dealing_exchange: DealingExchangeState,
|
||||
|
||||
pub(crate) key_generation: KeyDerivationState,
|
||||
|
||||
|
||||
pub(crate) key_validation: ValidationState,
|
||||
|
||||
|
||||
pub(crate) key_finalization: FinalizationState,
|
||||
}
|
||||
|
||||
@@ -267,7 +267,8 @@ impl DkgState {
|
||||
dkg_participant.address
|
||||
)
|
||||
}
|
||||
self.dealing_exchange.dealers
|
||||
self.dealing_exchange
|
||||
.dealers
|
||||
.insert(dkg_participant.assigned_index, dkg_participant);
|
||||
}
|
||||
}
|
||||
@@ -524,9 +525,11 @@ impl State {
|
||||
.receiver_index
|
||||
.ok_or(CoconutError::UnavailableReceiverIndex { epoch_id })
|
||||
}
|
||||
|
||||
pub fn proposal_id(&self, epoch_id: EpochId) -> Result<u64, CoconutError> {
|
||||
self.key_derivation_state(epoch_id)?.proposal_id.ok_or(CoconutError::UnavailableProposalId {epoch_id})
|
||||
|
||||
pub fn proposal_id(&self, epoch_id: EpochId) -> Result<u64, CoconutError> {
|
||||
self.key_derivation_state(epoch_id)?
|
||||
.proposal_id
|
||||
.ok_or(CoconutError::UnavailableProposalId { epoch_id })
|
||||
}
|
||||
|
||||
pub fn persistent_state_path(&self) -> &Path {
|
||||
@@ -557,6 +560,10 @@ impl State {
|
||||
self.coconut_keypair.invalidate()
|
||||
}
|
||||
|
||||
pub fn validate_coconut_keypair(&self) {
|
||||
self.coconut_keypair.validate()
|
||||
}
|
||||
|
||||
pub fn get_dealing(&self, epoch_id: EpochId, dealing_index: DealingIndex) -> Option<&Dealing> {
|
||||
self.generated_dealings
|
||||
.get(&epoch_id)
|
||||
|
||||
@@ -67,7 +67,7 @@ impl KeyPair {
|
||||
self.valid.load(Ordering::SeqCst)
|
||||
}
|
||||
|
||||
pub fn enable(&self) {
|
||||
pub fn validate(&self) {
|
||||
self.valid.store(true, Ordering::SeqCst);
|
||||
}
|
||||
|
||||
|
||||
@@ -125,7 +125,7 @@ pub(crate) async fn validate_keys(controllers: &mut [TestingDkgController], resh
|
||||
guard.dkg_epoch.state = EpochState::VerificationKeyFinalization { resharing }
|
||||
}
|
||||
|
||||
pub(crate) async fn finalize(controllers: &mut [TestingDkgController], resharing: bool) {
|
||||
pub(crate) async fn finalize(controllers: &mut [TestingDkgController]) {
|
||||
let epoch = controllers[0]
|
||||
.chain_state
|
||||
.lock()
|
||||
@@ -135,7 +135,7 @@ pub(crate) async fn finalize(controllers: &mut [TestingDkgController], resharing
|
||||
|
||||
for controller in controllers.iter_mut() {
|
||||
controller
|
||||
.verification_key_finalization(epoch, resharing)
|
||||
.verification_key_finalization(epoch)
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user