fixed nym-api tests
This commit is contained in:
@@ -286,7 +286,7 @@ impl<R: RngCore + CryptoRng> DkgController<R> {
|
||||
// it could be outdated and we can't use it for resharing
|
||||
let previous = epoch_id.saturating_sub(1);
|
||||
if old_keypair.issued_for_epoch != previous {
|
||||
warn!("our existing coconut keypair has been generated for an distant epoch ({} vs expected {previous} for resharing)", old_keypair.issued_for_epoch);
|
||||
warn!("our existing coconut keypair has been generated for a distant epoch ({} vs expected {previous} for resharing)", old_keypair.issued_for_epoch);
|
||||
// don't participate in resharing
|
||||
return Ok(());
|
||||
}
|
||||
@@ -475,6 +475,7 @@ pub(crate) mod tests {
|
||||
};
|
||||
use crate::coconut::tests::helpers::unchecked_decode_bte_key;
|
||||
use nym_coconut::{ttp_keygen, Parameters};
|
||||
use nym_coconut_dkg_common::types::DealerRegistrationDetails;
|
||||
use nym_dkg::bte::PublicKeyWithProof;
|
||||
|
||||
#[tokio::test]
|
||||
@@ -615,7 +616,7 @@ pub(crate) mod tests {
|
||||
let dealers = dealers_fixtures(&mut rng, 4);
|
||||
let self_dealer = dealers[0].clone();
|
||||
|
||||
let epoch = 0;
|
||||
let epoch = 1;
|
||||
|
||||
let mut keys = ttp_keygen(&Parameters::new(4).unwrap(), 3, 4).unwrap();
|
||||
let coconut_keypair = KeyPair::new();
|
||||
@@ -672,29 +673,42 @@ pub(crate) mod tests {
|
||||
let dealers = dealers_fixtures(&mut rng, 4);
|
||||
let self_dealer = dealers[0].clone();
|
||||
|
||||
let epoch = 0;
|
||||
let epoch = 1;
|
||||
|
||||
let mut keys = ttp_keygen(&Parameters::new(4).unwrap(), 3, 4).unwrap();
|
||||
let coconut_keypair = KeyPair::new();
|
||||
coconut_keypair
|
||||
.set(KeyPairWithEpoch::new(keys.pop().unwrap(), epoch))
|
||||
.set(KeyPairWithEpoch::new(keys.pop().unwrap(), epoch - 1))
|
||||
.await;
|
||||
|
||||
let initial_dealers = InitialReplacementData {
|
||||
initial_dealers: vec![self_dealer.address.clone()],
|
||||
initial_height: 100,
|
||||
};
|
||||
|
||||
let mut controller = TestingDkgControllerBuilder::default()
|
||||
.with_threshold(3)
|
||||
.with_dealers(dealers.clone())
|
||||
.with_as_dealer(self_dealer.clone())
|
||||
.with_keypair(coconut_keypair)
|
||||
.with_initial_epoch_id(epoch)
|
||||
.with_initial_dealers(initial_dealers)
|
||||
.build()
|
||||
.await;
|
||||
|
||||
let chain = controller.chain_state.clone();
|
||||
|
||||
// TODO: put that functionality in the builder
|
||||
chain
|
||||
.lock()
|
||||
.unwrap()
|
||||
.dkg_contract
|
||||
.dealers
|
||||
.entry(epoch - 1)
|
||||
.or_default()
|
||||
.insert(
|
||||
self_dealer.address.to_string(),
|
||||
DealerRegistrationDetails {
|
||||
bte_public_key_with_proof: self_dealer.bte_public_key_with_proof.clone(),
|
||||
ed25519_identity: self_dealer.ed25519_identity.clone(),
|
||||
announce_address: self_dealer.announce_address.clone(),
|
||||
},
|
||||
);
|
||||
|
||||
let key_size = controller.dkg_client.get_contract_state().await?.key_size;
|
||||
|
||||
let res = controller.dealing_exchange(epoch, true).await;
|
||||
|
||||
@@ -10,7 +10,8 @@ use crate::coconut::keys::KeyPair;
|
||||
use crate::coconut::tests::{DummyClient, SharedFakeChain};
|
||||
use cosmwasm_std::Addr;
|
||||
use nym_coconut::VerificationKey;
|
||||
use nym_coconut_dkg_common::types::{DealerDetails, EpochId, InitialReplacementData};
|
||||
use nym_coconut_dkg_common::dealer::DealerRegistrationDetails;
|
||||
use nym_coconut_dkg_common::types::{DealerDetails, EpochId};
|
||||
use nym_crypto::asymmetric::identity;
|
||||
use nym_dkg::bte::keys::KeyPair as DkgKeyPair;
|
||||
use nym_dkg::{NodeIndex, Threshold};
|
||||
@@ -81,7 +82,6 @@ pub struct TestingDkgControllerBuilder {
|
||||
threshold: Option<Threshold>,
|
||||
self_dealer: Option<DealerDetails>,
|
||||
dealers: Vec<DealerDetails>,
|
||||
initial_dealers: Option<InitialReplacementData>,
|
||||
}
|
||||
|
||||
impl TestingDkgControllerBuilder {
|
||||
@@ -127,11 +127,6 @@ impl TestingDkgControllerBuilder {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_initial_dealers(mut self, initial_dealers: InitialReplacementData) -> Self {
|
||||
self.initial_dealers = Some(initial_dealers);
|
||||
self
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn with_address(mut self, address: impl Into<String>) -> Self {
|
||||
let addr = address.into();
|
||||
@@ -181,20 +176,34 @@ impl TestingDkgControllerBuilder {
|
||||
// insert initial data into the chain state
|
||||
{
|
||||
let mut state_guard = chain_state.lock().unwrap();
|
||||
if let Some(threshold) = self.threshold {
|
||||
state_guard.dkg_contract.threshold = Some(threshold)
|
||||
}
|
||||
for dealer in self.dealers {
|
||||
state_guard
|
||||
.dkg_contract
|
||||
.dealers
|
||||
.insert(dealer.assigned_index, dealer);
|
||||
}
|
||||
if let Some(epoch_id) = self.epoch_id {
|
||||
state_guard.dkg_contract.epoch.epoch_id = epoch_id;
|
||||
}
|
||||
if let Some(initial_dealers) = self.initial_dealers {
|
||||
state_guard.dkg_contract.initial_dealers = Some(initial_dealers)
|
||||
if let Some(threshold) = self.threshold {
|
||||
state_guard.dkg_contract.threshold = Some(threshold)
|
||||
}
|
||||
let epoch_id = state_guard.dkg_contract.epoch.epoch_id;
|
||||
|
||||
for dealer in self.dealers {
|
||||
let epoch_dealers = state_guard
|
||||
.dkg_contract
|
||||
.dealers
|
||||
.entry(epoch_id)
|
||||
.or_default();
|
||||
|
||||
epoch_dealers.insert(
|
||||
dealer.address.to_string(),
|
||||
DealerRegistrationDetails {
|
||||
bte_public_key_with_proof: dealer.bte_public_key_with_proof,
|
||||
ed25519_identity: dealer.ed25519_identity,
|
||||
announce_address: dealer.announce_address,
|
||||
},
|
||||
);
|
||||
|
||||
state_guard
|
||||
.dkg_contract
|
||||
.dealer_indices
|
||||
.insert(dealer.address.to_string(), dealer.assigned_index);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+338
-281
@@ -21,15 +21,17 @@ use nym_coconut_bandwidth_contract_common::events::{
|
||||
DEPOSIT_VALUE,
|
||||
};
|
||||
use nym_coconut_bandwidth_contract_common::spend_credential::SpendCredentialResponse;
|
||||
use nym_coconut_dkg_common::dealer::{DealerDetails, DealerDetailsResponse, DealerType};
|
||||
use nym_coconut_dkg_common::dealer::{
|
||||
DealerDetails, DealerDetailsResponse, DealerType, RegisteredDealerDetails,
|
||||
};
|
||||
use nym_coconut_dkg_common::dealing::{
|
||||
DealerDealingsStatusResponse, DealingChunkInfo, DealingMetadata, DealingStatus,
|
||||
DealingStatusResponse, PartialContractDealing,
|
||||
};
|
||||
use nym_coconut_dkg_common::event_attributes::{DKG_PROPOSAL_ID, NODE_INDEX};
|
||||
use nym_coconut_dkg_common::types::{
|
||||
ChunkIndex, DealingIndex, EncodedBTEPublicKeyWithProof, Epoch, EpochId, EpochState,
|
||||
PartialContractDealingData, State as ContractState,
|
||||
ChunkIndex, DealerRegistrationDetails, DealingIndex, EncodedBTEPublicKeyWithProof, Epoch,
|
||||
EpochId, EpochState, PartialContractDealingData, State as ContractState,
|
||||
};
|
||||
use nym_coconut_dkg_common::verification_key::{ContractVKShare, VerificationKeyShare};
|
||||
use nym_coconut_interface::VerificationKey;
|
||||
@@ -38,7 +40,6 @@ use nym_contracts_common::IdentityKey;
|
||||
use nym_credentials::coconut::bandwidth::BandwidthVoucher;
|
||||
use nym_crypto::asymmetric::{encryption, identity};
|
||||
use nym_dkg::{NodeIndex, Threshold};
|
||||
use nym_mixnet_contract_common::BlockHeight;
|
||||
use nym_validator_client::nym_api::routes::{
|
||||
API_VERSION, BANDWIDTH, COCONUT_BLIND_SIGN, COCONUT_ROUTES,
|
||||
};
|
||||
@@ -53,7 +54,6 @@ use rand_07::RngCore;
|
||||
use rocket::http::Status;
|
||||
use rocket::local::asynchronous::Client;
|
||||
use std::collections::{BTreeMap, HashMap};
|
||||
use std::mem;
|
||||
use std::ops::Deref;
|
||||
use std::str::FromStr;
|
||||
use std::sync::atomic::{AtomicU64, Ordering};
|
||||
@@ -138,6 +138,10 @@ pub(crate) struct FakeDkgContractState {
|
||||
// pub(crate) dealers: HashMap<NodeIndex, DealerDetails>,
|
||||
// pub(crate) past_dealers: HashMap<NodeIndex, DealerDetails>,
|
||||
// pub(crate) initial_dealers: Option<InitialReplacementData>,
|
||||
pub(crate) dealer_indices: HashMap<String, NodeIndex>,
|
||||
|
||||
// map of epoch id -> dealer -> info
|
||||
pub(crate) dealers: HashMap<EpochId, HashMap<String, DealerRegistrationDetails>>,
|
||||
|
||||
// map of epoch id -> dealer -> dealings
|
||||
pub(crate) dealings: HashMap<EpochId, HashMap<String, HashMap<DealingIndex, Dealing>>>,
|
||||
@@ -151,41 +155,84 @@ pub(crate) struct FakeDkgContractState {
|
||||
}
|
||||
|
||||
impl FakeDkgContractState {
|
||||
pub(crate) fn verified_dealers(&self) -> Vec<Addr> {
|
||||
let epoch_id = self.epoch.epoch_id;
|
||||
let Some(shares) = self.verification_shares.get(&epoch_id) else {
|
||||
return Vec::new();
|
||||
};
|
||||
|
||||
shares
|
||||
.values()
|
||||
.filter(|s| s.verified)
|
||||
.map(|s| s.owner.clone())
|
||||
.collect()
|
||||
}
|
||||
// pub(crate) fn verified_dealers(&self) -> Vec<Addr> {
|
||||
// let epoch_id = self.epoch.epoch_id;
|
||||
// let Some(shares) = self.verification_shares.get(&epoch_id) else {
|
||||
// return Vec::new();
|
||||
// };
|
||||
//
|
||||
// shares
|
||||
// .values()
|
||||
// .filter(|s| s.verified)
|
||||
// .map(|s| s.owner.clone())
|
||||
// .collect()
|
||||
// }
|
||||
|
||||
fn reset_dkg_state(&mut self) {
|
||||
self.threshold = None;
|
||||
let dealers = mem::take(&mut self.dealers);
|
||||
for (index, details) in dealers {
|
||||
self.past_dealers.insert(index, details);
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn reset_epoch_in_reshare_mode(&mut self, block_height: BlockHeight) {
|
||||
if let Some(initial_dealers) = self.initial_dealers.as_mut() {
|
||||
initial_dealers.initial_height = block_height;
|
||||
} else {
|
||||
self.initial_dealers = Some(InitialReplacementData {
|
||||
initial_dealers: self.verified_dealers(),
|
||||
initial_height: block_height,
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn reset_epoch_in_reshare_mode(&mut self) {
|
||||
self.reset_dkg_state();
|
||||
self.epoch.state = EpochState::PublicKeySubmission { resharing: true };
|
||||
self.epoch.epoch_id += 1;
|
||||
}
|
||||
|
||||
pub(crate) fn reset_dkg(&mut self) {
|
||||
self.reset_dkg_state();
|
||||
self.epoch.state = EpochState::PublicKeySubmission { resharing: false };
|
||||
self.epoch.epoch_id += 1;
|
||||
}
|
||||
|
||||
pub(crate) fn get_registration_details(
|
||||
&self,
|
||||
addr: &str,
|
||||
epoch_id: EpochId,
|
||||
) -> Option<DealerRegistrationDetails> {
|
||||
self.dealers.get(&epoch_id)?.get(addr).cloned()
|
||||
}
|
||||
|
||||
pub(crate) fn get_dealer_details(
|
||||
&self,
|
||||
addr: &str,
|
||||
epoch_id: EpochId,
|
||||
) -> Option<DealerDetails> {
|
||||
let registration_details = self.get_registration_details(addr, epoch_id)?;
|
||||
let assigned_index = self.get_dealer_index(addr)?;
|
||||
|
||||
Some(DealerDetails {
|
||||
address: Addr::unchecked(addr),
|
||||
bte_public_key_with_proof: registration_details.bte_public_key_with_proof,
|
||||
ed25519_identity: registration_details.ed25519_identity,
|
||||
announce_address: registration_details.announce_address,
|
||||
assigned_index,
|
||||
})
|
||||
}
|
||||
|
||||
// implementation copied from our contract
|
||||
pub(crate) fn query_dealer_details(&self, addr: &str) -> DealerDetailsResponse {
|
||||
let current_epoch_id = self.epoch.epoch_id;
|
||||
|
||||
// if the address has registration data for the current epoch, it means it's an active dealer
|
||||
if let Some(dealer_details) = self.get_dealer_details(addr, current_epoch_id) {
|
||||
let assigned_index = dealer_details.assigned_index;
|
||||
return DealerDetailsResponse::new(
|
||||
Some(dealer_details),
|
||||
DealerType::Current { assigned_index },
|
||||
);
|
||||
}
|
||||
|
||||
// and if has had an assigned index it must have been a dealer at some point in the past
|
||||
if let Some(assigned_index) = self.get_dealer_index(addr) {
|
||||
return DealerDetailsResponse::new(None, DealerType::Past { assigned_index });
|
||||
}
|
||||
|
||||
DealerDetailsResponse::new(None, DealerType::Unknown)
|
||||
}
|
||||
|
||||
pub(crate) fn get_dealer_index(&self, addr: &str) -> Option<NodeIndex> {
|
||||
self.dealer_indices.get(addr).copied()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@@ -274,8 +321,8 @@ impl Default for FakeChainState {
|
||||
|
||||
dkg_contract: FakeDkgContractState {
|
||||
address: dkg_contract.as_ref().parse().unwrap(),
|
||||
dealer_indices: Default::default(),
|
||||
dealers: HashMap::new(),
|
||||
past_dealers: Default::default(),
|
||||
|
||||
epoch: Epoch::default(),
|
||||
contract_state: ContractState {
|
||||
@@ -287,7 +334,6 @@ impl Default for FakeChainState {
|
||||
dealings: HashMap::new(),
|
||||
verification_shares: HashMap::new(),
|
||||
threshold: None,
|
||||
initial_dealers: None,
|
||||
},
|
||||
group_contract: FakeGroupContractState {
|
||||
address: group_contract,
|
||||
@@ -307,6 +353,18 @@ impl Default for FakeChainState {
|
||||
}
|
||||
|
||||
impl FakeChainState {
|
||||
pub(crate) fn get_or_assign_dealer(&mut self, addr: &str) -> NodeIndex {
|
||||
if let Some(index) = self.dkg_contract.dealer_indices.get(addr) {
|
||||
*index
|
||||
} else {
|
||||
let new = self._counters.next_node_index();
|
||||
self.dkg_contract
|
||||
.dealer_indices
|
||||
.insert(addr.to_string(), new);
|
||||
new
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn total_group_weight(&self) -> u64 {
|
||||
self.group_contract.total_weight()
|
||||
}
|
||||
@@ -320,8 +378,12 @@ impl FakeChainState {
|
||||
}
|
||||
|
||||
pub(crate) fn advance_epoch_in_reshare_mode(&mut self) {
|
||||
self.dkg_contract
|
||||
.reset_epoch_in_reshare_mode(self.block_info.height)
|
||||
self.dkg_contract.reset_epoch_in_reshare_mode()
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub(crate) fn advance_epoch_in_reset_mode(&mut self) {
|
||||
self.dkg_contract.reset_dkg()
|
||||
}
|
||||
|
||||
// TODO: make it return a result
|
||||
@@ -519,25 +581,25 @@ impl DummyClient {
|
||||
// // self
|
||||
// }
|
||||
|
||||
async fn get_dealer_by_address(&self, address: &str) -> Option<DealerDetails> {
|
||||
let guard = self.state.lock().unwrap();
|
||||
for dealer in guard.dkg_contract.dealers.values() {
|
||||
if dealer.address.as_str() == address {
|
||||
return Some(dealer.clone());
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
async fn get_past_dealer_by_address(&self, address: &str) -> Option<DealerDetails> {
|
||||
let guard = self.state.lock().unwrap();
|
||||
for dealer in guard.dkg_contract.past_dealers.values() {
|
||||
if dealer.address.as_str() == address {
|
||||
return Some(dealer.clone());
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
// async fn get_dealer_by_address(&self, address: &str) -> Option<DealerDetails> {
|
||||
// let guard = self.state.lock().unwrap();
|
||||
// for dealer in guard.dkg_contract.dealers.values() {
|
||||
// if dealer.address.as_str() == address {
|
||||
// return Some(dealer.clone());
|
||||
// }
|
||||
// }
|
||||
// None
|
||||
// }
|
||||
//
|
||||
// async fn get_past_dealer_by_address(&self, address: &str) -> Option<DealerDetails> {
|
||||
// let guard = self.state.lock().unwrap();
|
||||
// for dealer in guard.dkg_contract.past_dealers.values() {
|
||||
// if dealer.address.as_str() == address {
|
||||
// return Some(dealer.clone());
|
||||
// }
|
||||
// }
|
||||
// None
|
||||
// }
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
@@ -653,24 +715,74 @@ impl super::client::Client for DummyClient {
|
||||
|
||||
async fn get_self_registered_dealer_details(&self) -> Result<DealerDetailsResponse> {
|
||||
let address = self.validator_address.as_ref();
|
||||
Ok(self
|
||||
.state
|
||||
.lock()
|
||||
.unwrap()
|
||||
.dkg_contract
|
||||
.query_dealer_details(address))
|
||||
}
|
||||
|
||||
if let Some(details) = self.get_dealer_by_address(address).await {
|
||||
return Ok(DealerDetailsResponse {
|
||||
details: Some(details),
|
||||
dealer_type: DealerType::Current,
|
||||
async fn get_registered_dealer_details(
|
||||
&self,
|
||||
epoch_id: EpochId,
|
||||
dealer: String,
|
||||
) -> Result<RegisteredDealerDetails> {
|
||||
let details = self
|
||||
.state
|
||||
.lock()
|
||||
.unwrap()
|
||||
.dkg_contract
|
||||
.dealers
|
||||
.get(&epoch_id)
|
||||
.and_then(|dealers| dealers.get(&dealer))
|
||||
.cloned();
|
||||
Ok(RegisteredDealerDetails { details })
|
||||
}
|
||||
|
||||
async fn get_dealer_dealings_status(
|
||||
&self,
|
||||
epoch_id: EpochId,
|
||||
dealer: String,
|
||||
) -> Result<DealerDealingsStatusResponse> {
|
||||
let guard = self.state.lock().unwrap();
|
||||
let key_size = guard.dkg_contract.contract_state.key_size;
|
||||
|
||||
let dealer_addr = Addr::unchecked(&dealer);
|
||||
|
||||
let Some(epoch_dealings) = guard.dkg_contract.dealings.get(&epoch_id) else {
|
||||
return Ok(DealerDealingsStatusResponse {
|
||||
epoch_id,
|
||||
dealer: dealer_addr,
|
||||
all_dealings_fully_submitted: false,
|
||||
dealing_submission_status: Default::default(),
|
||||
});
|
||||
};
|
||||
|
||||
let Some(dealer_dealings) = epoch_dealings.get(&dealer) else {
|
||||
return Ok(DealerDealingsStatusResponse {
|
||||
epoch_id,
|
||||
dealer: dealer_addr,
|
||||
all_dealings_fully_submitted: false,
|
||||
dealing_submission_status: Default::default(),
|
||||
});
|
||||
};
|
||||
|
||||
let mut dealing_submission_status: BTreeMap<DealingIndex, DealingStatus> = BTreeMap::new();
|
||||
for dealing_index in 0..key_size {
|
||||
let metadata = dealer_dealings
|
||||
.get(&dealing_index)
|
||||
.map(|d| d.metadata.clone());
|
||||
dealing_submission_status.insert(dealing_index, metadata.into());
|
||||
}
|
||||
|
||||
if let Some(details) = self.get_past_dealer_by_address(address).await {
|
||||
return Ok(DealerDetailsResponse {
|
||||
details: Some(details),
|
||||
dealer_type: DealerType::Past,
|
||||
});
|
||||
}
|
||||
|
||||
Ok(DealerDetailsResponse {
|
||||
details: None,
|
||||
dealer_type: DealerType::Unknown,
|
||||
Ok(DealerDealingsStatusResponse {
|
||||
epoch_id,
|
||||
dealer: Addr::unchecked(&dealer),
|
||||
all_dealings_fully_submitted: dealing_submission_status
|
||||
.values()
|
||||
.all(|d| d.fully_submitted),
|
||||
dealing_submission_status,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -699,17 +811,75 @@ impl super::client::Client for DummyClient {
|
||||
}
|
||||
|
||||
async fn get_current_dealers(&self) -> Result<Vec<DealerDetails>> {
|
||||
Ok(self
|
||||
.state
|
||||
.lock()
|
||||
.unwrap()
|
||||
.dkg_contract
|
||||
.dealers
|
||||
.values()
|
||||
.cloned()
|
||||
let chain = self.state.lock().unwrap();
|
||||
let current_epoch_id = chain.dkg_contract.epoch.epoch_id;
|
||||
|
||||
let Some(epoch_dealers) = chain.dkg_contract.dealers.get(¤t_epoch_id) else {
|
||||
return Ok(Vec::new());
|
||||
};
|
||||
|
||||
Ok(epoch_dealers
|
||||
.iter()
|
||||
.map(|(address, details)| {
|
||||
let assigned_index = chain.dkg_contract.get_dealer_index(address).unwrap();
|
||||
DealerDetails {
|
||||
address: Addr::unchecked(address),
|
||||
bte_public_key_with_proof: details.bte_public_key_with_proof.clone(),
|
||||
ed25519_identity: details.ed25519_identity.clone(),
|
||||
announce_address: details.announce_address.clone(),
|
||||
assigned_index,
|
||||
}
|
||||
})
|
||||
.collect())
|
||||
}
|
||||
|
||||
async fn get_dealing_metadata(
|
||||
&self,
|
||||
epoch_id: EpochId,
|
||||
dealer: String,
|
||||
dealing_index: DealingIndex,
|
||||
) -> Result<Option<DealingMetadata>> {
|
||||
let guard = self.state.lock().unwrap();
|
||||
|
||||
let Some(epoch_dealings) = guard.dkg_contract.dealings.get(&epoch_id) else {
|
||||
return Ok(None);
|
||||
};
|
||||
|
||||
let Some(dealer_dealings) = epoch_dealings.get(&dealer) else {
|
||||
return Ok(None);
|
||||
};
|
||||
|
||||
let Some(dealing) = dealer_dealings.get(&dealing_index) else {
|
||||
return Ok(None);
|
||||
};
|
||||
|
||||
Ok(Some(dealing.metadata.clone()))
|
||||
}
|
||||
|
||||
async fn get_dealing_chunk(
|
||||
&self,
|
||||
epoch_id: EpochId,
|
||||
dealer: &str,
|
||||
dealing_index: DealingIndex,
|
||||
chunk_index: ChunkIndex,
|
||||
) -> Result<Option<PartialContractDealingData>> {
|
||||
let guard = self.state.lock().unwrap();
|
||||
|
||||
let Some(epoch_dealings) = guard.dkg_contract.dealings.get(&epoch_id) else {
|
||||
return Ok(None);
|
||||
};
|
||||
|
||||
let Some(dealer_dealings) = epoch_dealings.get(dealer) else {
|
||||
return Ok(None);
|
||||
};
|
||||
|
||||
let Some(dealing) = dealer_dealings.get(&dealing_index) else {
|
||||
return Ok(None);
|
||||
};
|
||||
|
||||
Ok(dealing.chunks.get(&chunk_index).cloned())
|
||||
}
|
||||
|
||||
async fn get_verification_key_share(
|
||||
&self,
|
||||
epoch_id: EpochId,
|
||||
@@ -733,7 +903,6 @@ impl super::client::Client for DummyClient {
|
||||
Some(epoch_shares) => Ok(epoch_shares.values().cloned().collect()),
|
||||
}
|
||||
}
|
||||
|
||||
async fn vote_proposal(
|
||||
&self,
|
||||
proposal_id: u64,
|
||||
@@ -819,43 +988,23 @@ impl super::client::Client for DummyClient {
|
||||
announce_address: String,
|
||||
_resharing: bool,
|
||||
) -> Result<ExecuteResult> {
|
||||
let assigned_index = if let Some(already_registered) = self
|
||||
.get_dealer_by_address(self.validator_address.as_ref())
|
||||
.await
|
||||
{
|
||||
// current dealer
|
||||
already_registered.assigned_index
|
||||
} else if let Some(registered_in_the_past) = self
|
||||
.get_past_dealer_by_address(self.validator_address.as_ref())
|
||||
.await
|
||||
{
|
||||
// past dealer
|
||||
let index = registered_in_the_past.assigned_index;
|
||||
let mut guard = self.state.lock().unwrap();
|
||||
guard
|
||||
.dkg_contract
|
||||
.dealers
|
||||
.insert(index, registered_in_the_past);
|
||||
|
||||
index
|
||||
} else {
|
||||
// new dealer
|
||||
let mut guard = self.state.lock().unwrap();
|
||||
let assigned_index = guard._counters.next_node_index();
|
||||
|
||||
guard.dkg_contract.dealers.insert(
|
||||
assigned_index,
|
||||
DealerDetails {
|
||||
address: Addr::unchecked(self.validator_address.to_string()),
|
||||
bte_public_key_with_proof,
|
||||
ed25519_identity: identity_key,
|
||||
announce_address,
|
||||
assigned_index,
|
||||
},
|
||||
);
|
||||
assigned_index
|
||||
};
|
||||
let mut guard = self.state.lock().unwrap();
|
||||
let assigned_index = guard.get_or_assign_dealer(self.validator_address.as_ref());
|
||||
let epoch = guard.dkg_contract.epoch.epoch_id;
|
||||
|
||||
let dealer_details = DealerRegistrationDetails {
|
||||
bte_public_key_with_proof,
|
||||
ed25519_identity: identity_key,
|
||||
announce_address,
|
||||
};
|
||||
|
||||
let epoch_dealers = guard.dkg_contract.dealers.entry(epoch).or_default();
|
||||
if !epoch_dealers.contains_key(self.validator_address.as_ref()) {
|
||||
epoch_dealers.insert(self.validator_address.to_string(), dealer_details);
|
||||
} else {
|
||||
unimplemented!("already registered")
|
||||
}
|
||||
|
||||
let transaction_hash = guard._counters.next_tx_hash();
|
||||
|
||||
Ok(ExecuteResult {
|
||||
@@ -869,174 +1018,6 @@ impl super::client::Client for DummyClient {
|
||||
gas_info: Default::default(),
|
||||
})
|
||||
}
|
||||
async fn submit_verification_key_share(
|
||||
&self,
|
||||
share: VerificationKeyShare,
|
||||
resharing: bool,
|
||||
) -> Result<ExecuteResult> {
|
||||
let address = self.validator_address.to_string();
|
||||
|
||||
let Some(dealer_details) = self.get_dealer_by_address(&address).await else {
|
||||
// Just throw some error, not really the correct one
|
||||
return Err(CoconutError::DepositEncrKeyNotFound);
|
||||
};
|
||||
|
||||
let mut chain = self.state.lock().unwrap();
|
||||
let dkg_contract = chain.dkg_contract.address.clone();
|
||||
let epoch_id = chain.dkg_contract.epoch.epoch_id;
|
||||
|
||||
chain
|
||||
.dkg_contract
|
||||
.verification_shares
|
||||
.entry(epoch_id)
|
||||
.or_default()
|
||||
.insert(
|
||||
self.validator_address.to_string(),
|
||||
ContractVKShare {
|
||||
share,
|
||||
announce_address: dealer_details.announce_address.clone(),
|
||||
node_index: dealer_details.assigned_index,
|
||||
owner: Addr::unchecked(&address),
|
||||
epoch_id,
|
||||
verified: false,
|
||||
},
|
||||
);
|
||||
|
||||
let proposal_id = chain._counters.next_proposal_id();
|
||||
let verify_vk_share_req =
|
||||
nym_coconut_dkg_common::msg::ExecuteMsg::VerifyVerificationKeyShare {
|
||||
owner: address,
|
||||
resharing,
|
||||
};
|
||||
let verify_vk_share_msg = CosmosMsg::Wasm(WasmMsg::Execute {
|
||||
contract_addr: chain.dkg_contract.address.to_string(),
|
||||
msg: to_binary(&verify_vk_share_req).unwrap(),
|
||||
funds: vec![],
|
||||
});
|
||||
let proposal = Proposal {
|
||||
title: String::new(),
|
||||
description: String::new(),
|
||||
msgs: vec![verify_vk_share_msg],
|
||||
status: cw3::Status::Open,
|
||||
expires: cw_utils::Expiration::Never {},
|
||||
threshold: cw_utils::Threshold::AbsolutePercentage {
|
||||
percentage: Decimal::from_ratio(2u32, 3u32),
|
||||
},
|
||||
total_weight: chain.total_group_weight(),
|
||||
votes: Votes::yes(0),
|
||||
proposer: Addr::unchecked(dkg_contract.as_ref()),
|
||||
deposit: None,
|
||||
start_height: 0,
|
||||
};
|
||||
chain
|
||||
.multisig_contract
|
||||
.proposals
|
||||
.insert(proposal_id, proposal);
|
||||
let transaction_hash = chain._counters.next_tx_hash();
|
||||
Ok(ExecuteResult {
|
||||
logs: vec![Log {
|
||||
msg_index: 0,
|
||||
events: vec![cosmwasm_std::Event::new("wasm")
|
||||
.add_attribute(DKG_PROPOSAL_ID, proposal_id.to_string())],
|
||||
}],
|
||||
data: Default::default(),
|
||||
transaction_hash,
|
||||
gas_info: Default::default(),
|
||||
})
|
||||
}
|
||||
|
||||
async fn get_dealer_dealings_status(
|
||||
&self,
|
||||
epoch_id: EpochId,
|
||||
dealer: String,
|
||||
) -> Result<DealerDealingsStatusResponse> {
|
||||
let guard = self.state.lock().unwrap();
|
||||
let key_size = guard.dkg_contract.contract_state.key_size;
|
||||
|
||||
let dealer_addr = Addr::unchecked(&dealer);
|
||||
|
||||
let Some(epoch_dealings) = guard.dkg_contract.dealings.get(&epoch_id) else {
|
||||
return Ok(DealerDealingsStatusResponse {
|
||||
epoch_id,
|
||||
dealer: dealer_addr,
|
||||
all_dealings_fully_submitted: false,
|
||||
dealing_submission_status: Default::default(),
|
||||
});
|
||||
};
|
||||
|
||||
let Some(dealer_dealings) = epoch_dealings.get(&dealer) else {
|
||||
return Ok(DealerDealingsStatusResponse {
|
||||
epoch_id,
|
||||
dealer: dealer_addr,
|
||||
all_dealings_fully_submitted: false,
|
||||
dealing_submission_status: Default::default(),
|
||||
});
|
||||
};
|
||||
|
||||
let mut dealing_submission_status: BTreeMap<DealingIndex, DealingStatus> = BTreeMap::new();
|
||||
for dealing_index in 0..key_size {
|
||||
let metadata = dealer_dealings
|
||||
.get(&dealing_index)
|
||||
.map(|d| d.metadata.clone());
|
||||
dealing_submission_status.insert(dealing_index, metadata.into());
|
||||
}
|
||||
|
||||
Ok(DealerDealingsStatusResponse {
|
||||
epoch_id,
|
||||
dealer: Addr::unchecked(&dealer),
|
||||
all_dealings_fully_submitted: dealing_submission_status
|
||||
.values()
|
||||
.all(|d| d.fully_submitted),
|
||||
dealing_submission_status,
|
||||
})
|
||||
}
|
||||
|
||||
async fn get_dealing_metadata(
|
||||
&self,
|
||||
epoch_id: EpochId,
|
||||
dealer: String,
|
||||
dealing_index: DealingIndex,
|
||||
) -> Result<Option<DealingMetadata>> {
|
||||
let guard = self.state.lock().unwrap();
|
||||
|
||||
let Some(epoch_dealings) = guard.dkg_contract.dealings.get(&epoch_id) else {
|
||||
return Ok(None);
|
||||
};
|
||||
|
||||
let Some(dealer_dealings) = epoch_dealings.get(&dealer) else {
|
||||
return Ok(None);
|
||||
};
|
||||
|
||||
let Some(dealing) = dealer_dealings.get(&dealing_index) else {
|
||||
return Ok(None);
|
||||
};
|
||||
|
||||
Ok(Some(dealing.metadata.clone()))
|
||||
}
|
||||
|
||||
async fn get_dealing_chunk(
|
||||
&self,
|
||||
epoch_id: EpochId,
|
||||
dealer: &str,
|
||||
dealing_index: DealingIndex,
|
||||
chunk_index: ChunkIndex,
|
||||
) -> Result<Option<PartialContractDealingData>> {
|
||||
let guard = self.state.lock().unwrap();
|
||||
|
||||
let Some(epoch_dealings) = guard.dkg_contract.dealings.get(&epoch_id) else {
|
||||
return Ok(None);
|
||||
};
|
||||
|
||||
let Some(dealer_dealings) = epoch_dealings.get(dealer) else {
|
||||
return Ok(None);
|
||||
};
|
||||
|
||||
let Some(dealing) = dealer_dealings.get(&dealing_index) else {
|
||||
return Ok(None);
|
||||
};
|
||||
|
||||
Ok(dealing.chunks.get(&chunk_index).cloned())
|
||||
}
|
||||
|
||||
async fn submit_dealing_metadata(
|
||||
&self,
|
||||
@@ -1104,6 +1085,82 @@ impl super::client::Client for DummyClient {
|
||||
gas_info: Default::default(),
|
||||
})
|
||||
}
|
||||
|
||||
async fn submit_verification_key_share(
|
||||
&self,
|
||||
share: VerificationKeyShare,
|
||||
resharing: bool,
|
||||
) -> Result<ExecuteResult> {
|
||||
let mut chain = self.state.lock().unwrap();
|
||||
|
||||
let address = self.validator_address.to_string();
|
||||
let epoch_id = chain.dkg_contract.epoch.epoch_id;
|
||||
let Some(dealer_details) = chain.dkg_contract.get_dealer_details(&address, epoch_id) else {
|
||||
// Just throw some error, not really the correct one
|
||||
return Err(CoconutError::DepositEncrKeyNotFound);
|
||||
};
|
||||
|
||||
let dkg_contract = chain.dkg_contract.address.clone();
|
||||
|
||||
chain
|
||||
.dkg_contract
|
||||
.verification_shares
|
||||
.entry(epoch_id)
|
||||
.or_default()
|
||||
.insert(
|
||||
self.validator_address.to_string(),
|
||||
ContractVKShare {
|
||||
share,
|
||||
announce_address: dealer_details.announce_address.clone(),
|
||||
node_index: dealer_details.assigned_index,
|
||||
owner: Addr::unchecked(&address),
|
||||
epoch_id,
|
||||
verified: false,
|
||||
},
|
||||
);
|
||||
|
||||
let proposal_id = chain._counters.next_proposal_id();
|
||||
let verify_vk_share_req =
|
||||
nym_coconut_dkg_common::msg::ExecuteMsg::VerifyVerificationKeyShare {
|
||||
owner: address,
|
||||
resharing,
|
||||
};
|
||||
let verify_vk_share_msg = CosmosMsg::Wasm(WasmMsg::Execute {
|
||||
contract_addr: chain.dkg_contract.address.to_string(),
|
||||
msg: to_binary(&verify_vk_share_req).unwrap(),
|
||||
funds: vec![],
|
||||
});
|
||||
let proposal = Proposal {
|
||||
title: String::new(),
|
||||
description: String::new(),
|
||||
msgs: vec![verify_vk_share_msg],
|
||||
status: cw3::Status::Open,
|
||||
expires: cw_utils::Expiration::Never {},
|
||||
threshold: cw_utils::Threshold::AbsolutePercentage {
|
||||
percentage: Decimal::from_ratio(2u32, 3u32),
|
||||
},
|
||||
total_weight: chain.total_group_weight(),
|
||||
votes: Votes::yes(0),
|
||||
proposer: Addr::unchecked(dkg_contract.as_ref()),
|
||||
deposit: None,
|
||||
start_height: 0,
|
||||
};
|
||||
chain
|
||||
.multisig_contract
|
||||
.proposals
|
||||
.insert(proposal_id, proposal);
|
||||
let transaction_hash = chain._counters.next_tx_hash();
|
||||
Ok(ExecuteResult {
|
||||
logs: vec![Log {
|
||||
msg_index: 0,
|
||||
events: vec![cosmwasm_std::Event::new("wasm")
|
||||
.add_attribute(DKG_PROPOSAL_ID, proposal_id.to_string())],
|
||||
}],
|
||||
data: Default::default(),
|
||||
transaction_hash,
|
||||
gas_info: Default::default(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
|
||||
Reference in New Issue
Block a user