revamped dealers storage structure (for txs)
This commit is contained in:
@@ -17,9 +17,7 @@ pub use nym_coconut_dkg_common::{
|
||||
DealingMetadataResponse, DealingStatusResponse,
|
||||
},
|
||||
msg::QueryMsg as DkgQueryMsg,
|
||||
types::{
|
||||
DealerDetails, DealingIndex, Epoch, EpochId, EpochState, InitialReplacementData, State,
|
||||
},
|
||||
types::{DealerDetails, DealingIndex, Epoch, EpochId, EpochState, State},
|
||||
verification_key::{ContractVKShare, PagedVKSharesResponse, VkShareResponse},
|
||||
};
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ use crate::{
|
||||
DealerDealingsStatusResponse, DealingChunkResponse, DealingChunkStatusResponse,
|
||||
DealingMetadataResponse, DealingStatusResponse,
|
||||
},
|
||||
types::{Epoch, InitialReplacementData, State},
|
||||
types::{Epoch, State},
|
||||
verification_key::{PagedVKSharesResponse, VkShareResponse},
|
||||
};
|
||||
#[cfg(feature = "schema")]
|
||||
@@ -53,7 +53,6 @@ pub enum ExecuteMsg {
|
||||
|
||||
CommitDealingsChunk {
|
||||
chunk: PartialContractDealing,
|
||||
resharing: bool,
|
||||
},
|
||||
|
||||
CommitVerificationKeyShare {
|
||||
|
||||
@@ -21,12 +21,6 @@ pub type DealingIndex = u32;
|
||||
pub type ChunkIndex = u16;
|
||||
pub type PartialContractDealingData = ContractSafeBytes;
|
||||
|
||||
#[cw_serde]
|
||||
pub struct InitialReplacementData {
|
||||
pub initial_dealers: Vec<Addr>,
|
||||
pub initial_height: u64,
|
||||
}
|
||||
|
||||
#[cw_serde]
|
||||
#[derive(Copy)]
|
||||
pub struct TimeConfiguration {
|
||||
|
||||
@@ -10,13 +10,10 @@ use crate::dealings::queries::{
|
||||
query_dealing_metadata, query_dealing_status,
|
||||
};
|
||||
use crate::dealings::transactions::{try_commit_dealings_chunk, try_submit_dealings_metadata};
|
||||
use crate::epoch_state::queries::{
|
||||
query_current_epoch, query_current_epoch_threshold, query_initial_dealers,
|
||||
};
|
||||
use crate::epoch_state::queries::{query_current_epoch, query_current_epoch_threshold};
|
||||
use crate::epoch_state::storage::CURRENT_EPOCH;
|
||||
use crate::epoch_state::transactions::{
|
||||
try_advance_epoch_state, try_initiate_dkg, try_surpassed_threshold, try_trigger_reset,
|
||||
try_trigger_resharing,
|
||||
try_advance_epoch_state, try_initiate_dkg, try_trigger_reset, try_trigger_resharing,
|
||||
};
|
||||
use crate::error::ContractError;
|
||||
use crate::state::queries::query_state;
|
||||
@@ -109,8 +106,8 @@ pub fn execute(
|
||||
chunks,
|
||||
resharing,
|
||||
} => try_submit_dealings_metadata(deps, info, dealing_index, chunks, resharing),
|
||||
ExecuteMsg::CommitDealingsChunk { chunk, resharing } => {
|
||||
try_commit_dealings_chunk(deps, env, info, chunk, resharing)
|
||||
ExecuteMsg::CommitDealingsChunk { chunk } => {
|
||||
try_commit_dealings_chunk(deps, env, info, chunk)
|
||||
}
|
||||
ExecuteMsg::CommitVerificationKeyShare { share, resharing } => {
|
||||
try_commit_verification_key_share(deps, env, info, share, resharing)
|
||||
@@ -118,7 +115,7 @@ pub fn execute(
|
||||
ExecuteMsg::VerifyVerificationKeyShare { owner, resharing } => {
|
||||
try_verify_verification_key_share(deps, info, owner, resharing)
|
||||
}
|
||||
ExecuteMsg::SurpassedThreshold {} => try_surpassed_threshold(deps, env),
|
||||
ExecuteMsg::SurpassedThreshold {} => todo!(),
|
||||
ExecuteMsg::AdvanceEpochState {} => try_advance_epoch_state(deps, env),
|
||||
ExecuteMsg::TriggerReset {} => try_trigger_reset(deps, env, info),
|
||||
ExecuteMsg::TriggerResharing {} => try_trigger_resharing(deps, env, info),
|
||||
@@ -133,7 +130,7 @@ pub fn query(deps: Deps<'_>, _env: Env, msg: QueryMsg) -> Result<QueryResponse,
|
||||
QueryMsg::GetCurrentEpochThreshold {} => {
|
||||
to_binary(&query_current_epoch_threshold(deps.storage)?)?
|
||||
}
|
||||
QueryMsg::GetInitialDealers {} => to_binary(&query_initial_dealers(deps.storage)?)?,
|
||||
QueryMsg::GetInitialDealers {} => todo!(),
|
||||
QueryMsg::GetDealerDetails { dealer_address } => {
|
||||
to_binary(&query_dealer_details(deps, dealer_address)?)?
|
||||
}
|
||||
|
||||
@@ -1,53 +1,55 @@
|
||||
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::dealers::storage::{self, IndexedDealersMap};
|
||||
use crate::dealers::storage::{self};
|
||||
use cosmwasm_std::{Deps, Order, StdResult};
|
||||
use cw_storage_plus::Bound;
|
||||
use nym_coconut_dkg_common::dealer::{DealerDetailsResponse, DealerType, PagedDealerResponse};
|
||||
|
||||
fn query_dealers(
|
||||
deps: Deps<'_>,
|
||||
start_after: Option<String>,
|
||||
limit: Option<u32>,
|
||||
underlying_map: &IndexedDealersMap<'_>,
|
||||
) -> StdResult<PagedDealerResponse> {
|
||||
let limit = limit
|
||||
.unwrap_or(storage::DEALERS_PAGE_DEFAULT_LIMIT)
|
||||
.min(storage::DEALERS_PAGE_MAX_LIMIT) as usize;
|
||||
|
||||
let addr = start_after
|
||||
.map(|addr| deps.api.addr_validate(&addr))
|
||||
.transpose()?;
|
||||
|
||||
let start = addr.as_ref().map(Bound::exclusive);
|
||||
|
||||
let dealers = underlying_map
|
||||
.range(deps.storage, start, None, Order::Ascending)
|
||||
.take(limit)
|
||||
.map(|res| res.map(|item| item.1))
|
||||
.collect::<StdResult<Vec<_>>>()?;
|
||||
|
||||
let start_next_after = dealers.last().map(|dealer| dealer.address.clone());
|
||||
|
||||
Ok(PagedDealerResponse::new(dealers, limit, start_next_after))
|
||||
}
|
||||
// fn query_dealers(
|
||||
// deps: Deps<'_>,
|
||||
// start_after: Option<String>,
|
||||
// limit: Option<u32>,
|
||||
// underlying_map: &IndexedDealersMap<'_>,
|
||||
// ) -> StdResult<PagedDealerResponse> {
|
||||
// let limit = limit
|
||||
// .unwrap_or(storage::DEALERS_PAGE_DEFAULT_LIMIT)
|
||||
// .min(storage::DEALERS_PAGE_MAX_LIMIT) as usize;
|
||||
//
|
||||
// let addr = start_after
|
||||
// .map(|addr| deps.api.addr_validate(&addr))
|
||||
// .transpose()?;
|
||||
//
|
||||
// let start = addr.as_ref().map(Bound::exclusive);
|
||||
//
|
||||
// let dealers = underlying_map
|
||||
// .range(deps.storage, start, None, Order::Ascending)
|
||||
// .take(limit)
|
||||
// .map(|res| res.map(|item| item.1))
|
||||
// .collect::<StdResult<Vec<_>>>()?;
|
||||
//
|
||||
// let start_next_after = dealers.last().map(|dealer| dealer.address.clone());
|
||||
//
|
||||
// Ok(PagedDealerResponse::new(dealers, limit, start_next_after))
|
||||
// }
|
||||
|
||||
pub fn query_dealer_details(
|
||||
deps: Deps<'_>,
|
||||
dealer_address: String,
|
||||
) -> StdResult<DealerDetailsResponse> {
|
||||
let addr = deps.api.addr_validate(&dealer_address)?;
|
||||
if let Some(current) = storage::current_dealers().may_load(deps.storage, &addr)? {
|
||||
return Ok(DealerDetailsResponse::new(
|
||||
Some(current),
|
||||
DealerType::Current,
|
||||
));
|
||||
}
|
||||
if let Some(past) = storage::past_dealers().may_load(deps.storage, &addr)? {
|
||||
return Ok(DealerDetailsResponse::new(Some(past), DealerType::Past));
|
||||
}
|
||||
Ok(DealerDetailsResponse::new(None, DealerType::Unknown))
|
||||
|
||||
todo!()
|
||||
// if let Some(current) = storage::current_dealers().may_load(deps.storage, &addr)? {
|
||||
// return Ok(DealerDetailsResponse::new(
|
||||
// Some(current),
|
||||
// DealerType::Current,
|
||||
// ));
|
||||
// }
|
||||
// if let Some(past) = storage::past_dealers().may_load(deps.storage, &addr)? {
|
||||
// return Ok(DealerDetailsResponse::new(Some(past), DealerType::Past));
|
||||
// }
|
||||
// Ok(DealerDetailsResponse::new(None, DealerType::Unknown))
|
||||
}
|
||||
|
||||
pub fn query_current_dealers_paged(
|
||||
@@ -55,7 +57,8 @@ pub fn query_current_dealers_paged(
|
||||
start_after: Option<String>,
|
||||
limit: Option<u32>,
|
||||
) -> StdResult<PagedDealerResponse> {
|
||||
query_dealers(deps, start_after, limit, &storage::current_dealers())
|
||||
todo!()
|
||||
// query_dealers(deps, start_after, limit, &storage::current_dealers())
|
||||
}
|
||||
|
||||
pub fn query_past_dealers_paged(
|
||||
@@ -63,7 +66,8 @@ pub fn query_past_dealers_paged(
|
||||
start_after: Option<String>,
|
||||
limit: Option<u32>,
|
||||
) -> StdResult<PagedDealerResponse> {
|
||||
query_dealers(deps, start_after, limit, &storage::past_dealers())
|
||||
todo!()
|
||||
// query_dealers(deps, start_after, limit, &storage::past_dealers())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@@ -1,50 +1,95 @@
|
||||
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::error::ContractError;
|
||||
use crate::Dealer;
|
||||
use cosmwasm_std::{Addr, StdResult, Storage};
|
||||
use cw_storage_plus::{Index, IndexList, IndexedMap, Item, Map, UniqueIndex};
|
||||
use nym_coconut_dkg_common::types::{DealerDetails, DealerRegistrationDetails, EpochId, NodeIndex};
|
||||
|
||||
const CURRENT_DEALERS_PK: &str = "crd";
|
||||
const PAST_DEALERS_PK: &str = "ptd";
|
||||
const DEALERS_NODE_INDEX_IDX_NAMESPACE: &str = "dni";
|
||||
|
||||
pub(crate) const DEALERS_PAGE_MAX_LIMIT: u32 = 75;
|
||||
pub(crate) const DEALERS_PAGE_DEFAULT_LIMIT: u32 = 50;
|
||||
pub(crate) const DEALERS_PAGE_MAX_LIMIT: u32 = 50;
|
||||
pub(crate) const DEALERS_PAGE_DEFAULT_LIMIT: u32 = 20;
|
||||
|
||||
pub(crate) const NODE_INDEX_COUNTER: Item<NodeIndex> = Item::new("node_index_counter");
|
||||
|
||||
// TODO:
|
||||
pub(crate) const DEALERS_INDICES: Map<Dealer, NodeIndex> = Map::new("dealer_index");
|
||||
|
||||
pub(crate) const EPOCH_DEALERS_MAP: Map<(EpochId, Dealer), DealerRegistrationDetails> =
|
||||
Map::new("epoch_dealers");
|
||||
|
||||
pub(crate) type IndexedDealersMap<'a> = IndexedMap<'a, &'a Addr, DealerDetails, DealersIndex<'a>>;
|
||||
|
||||
pub(crate) struct DealersIndex<'a> {
|
||||
pub(crate) node_index: UniqueIndex<'a, NodeIndex, DealerDetails>,
|
||||
}
|
||||
|
||||
impl<'a> IndexList<DealerDetails> for DealersIndex<'a> {
|
||||
fn get_indexes(&'_ self) -> Box<dyn Iterator<Item = &'_ dyn Index<DealerDetails>> + '_> {
|
||||
let v: Vec<&dyn Index<DealerDetails>> = vec![&self.node_index];
|
||||
Box::new(v.into_iter())
|
||||
/// Attempts to retrieve a pre-assign node index associated with given dealer.
|
||||
/// If one doesn't exist, a new one is assigned.
|
||||
pub(crate) fn get_or_assign_index(
|
||||
storage: &mut dyn Storage,
|
||||
dealer: Dealer,
|
||||
) -> StdResult<NodeIndex> {
|
||||
if let Some(index) = DEALERS_INDICES.may_load(storage, dealer)? {
|
||||
return Ok(index);
|
||||
}
|
||||
let index = next_node_index(storage)?;
|
||||
DEALERS_INDICES.save(storage, dealer, &index)?;
|
||||
Ok(index)
|
||||
}
|
||||
|
||||
pub(crate) fn current_dealers<'a>() -> IndexedDealersMap<'a> {
|
||||
let indexes = DealersIndex {
|
||||
node_index: UniqueIndex::new(|d| d.assigned_index, DEALERS_NODE_INDEX_IDX_NAMESPACE),
|
||||
};
|
||||
IndexedMap::new(CURRENT_DEALERS_PK, indexes)
|
||||
pub(crate) fn save_dealer_details_if_not_a_dealer(
|
||||
storage: &mut dyn Storage,
|
||||
dealer: Dealer,
|
||||
epoch_id: EpochId,
|
||||
details: DealerRegistrationDetails,
|
||||
) -> Result<(), ContractError> {
|
||||
if EPOCH_DEALERS_MAP.has(storage, (epoch_id, dealer)) {
|
||||
return Err(ContractError::AlreadyADealer);
|
||||
}
|
||||
EPOCH_DEALERS_MAP.save(storage, (epoch_id, dealer), &details)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn past_dealers<'a>() -> IndexedDealersMap<'a> {
|
||||
let indexes = DealersIndex {
|
||||
node_index: UniqueIndex::new(|d| d.assigned_index, DEALERS_NODE_INDEX_IDX_NAMESPACE),
|
||||
};
|
||||
IndexedMap::new(PAST_DEALERS_PK, indexes)
|
||||
pub(crate) fn ensure_dealer(
|
||||
storage: &dyn Storage,
|
||||
dealer: Dealer,
|
||||
epoch_id: EpochId,
|
||||
) -> Result<(), ContractError> {
|
||||
if !EPOCH_DEALERS_MAP.has(storage, (epoch_id, dealer)) {
|
||||
return Err(ContractError::NotADealer { epoch_id });
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// note: `epoch_id` is provided purely for the error message. it has nothing to do with storage retrieval
|
||||
pub(crate) fn get_dealer_index(
|
||||
storage: &dyn Storage,
|
||||
dealer: Dealer,
|
||||
epoch_id: EpochId,
|
||||
) -> Result<NodeIndex, ContractError> {
|
||||
DEALERS_INDICES
|
||||
.may_load(storage, dealer)?
|
||||
.ok_or(ContractError::NotADealer { epoch_id })
|
||||
}
|
||||
|
||||
pub(crate) fn get_registration_details(
|
||||
storage: &dyn Storage,
|
||||
dealer: Dealer,
|
||||
epoch_id: EpochId,
|
||||
) -> Result<DealerRegistrationDetails, ContractError> {
|
||||
EPOCH_DEALERS_MAP
|
||||
.may_load(storage, (epoch_id, dealer))?
|
||||
.ok_or(ContractError::NotADealer { epoch_id })
|
||||
}
|
||||
|
||||
pub(crate) fn get_dealer_details(
|
||||
storage: &dyn Storage,
|
||||
dealer: Dealer,
|
||||
epoch_id: EpochId,
|
||||
) -> Result<DealerDetails, ContractError> {
|
||||
let registration_details = get_registration_details(storage, dealer, epoch_id)?;
|
||||
let assigned_index = get_dealer_index(storage, dealer, epoch_id)?;
|
||||
Ok(DealerDetails {
|
||||
address: dealer.to_owned(),
|
||||
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,
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn next_node_index(store: &mut dyn Storage) -> StdResult<NodeIndex> {
|
||||
|
||||
@@ -1,34 +1,22 @@
|
||||
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::dealers::storage as dealers_storage;
|
||||
use crate::epoch_state::storage::{CURRENT_EPOCH, INITIAL_REPLACEMENT_DATA};
|
||||
use crate::dealers::storage::{get_or_assign_index, save_dealer_details_if_not_a_dealer};
|
||||
use crate::epoch_state::storage::CURRENT_EPOCH;
|
||||
use crate::epoch_state::utils::check_epoch_state;
|
||||
use crate::error::ContractError;
|
||||
use crate::state::storage::STATE;
|
||||
use cosmwasm_std::{Addr, DepsMut, MessageInfo, Response, StdResult};
|
||||
use nym_coconut_dkg_common::types::{DealerDetails, EncodedBTEPublicKeyWithProof, EpochState};
|
||||
use crate::Dealer;
|
||||
use cosmwasm_std::{Deps, DepsMut, MessageInfo, Response, StdResult};
|
||||
use nym_coconut_dkg_common::dealer::DealerRegistrationDetails;
|
||||
use nym_coconut_dkg_common::types::{EncodedBTEPublicKeyWithProof, EpochState};
|
||||
|
||||
// currently we only require that
|
||||
// a) it's part of the signer group
|
||||
// b) it isn't already a dealer
|
||||
fn verify_dealer(deps: DepsMut<'_>, dealer: &Addr, resharing: bool) -> Result<(), ContractError> {
|
||||
if dealers_storage::current_dealers()
|
||||
.may_load(deps.storage, dealer)?
|
||||
.is_some()
|
||||
{
|
||||
return Err(ContractError::AlreadyADealer);
|
||||
}
|
||||
fn ensure_group_member(deps: Deps, dealer: Dealer) -> Result<(), ContractError> {
|
||||
let state = STATE.load(deps.storage)?;
|
||||
|
||||
let height = if resharing {
|
||||
Some(INITIAL_REPLACEMENT_DATA.load(deps.storage)?.initial_height)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
state
|
||||
.group_addr
|
||||
.is_voting_member(&deps.querier, dealer, height)?
|
||||
.is_voting_member(&deps.querier, dealer, None)?
|
||||
.ok_or(ContractError::Unauthorized {})?;
|
||||
|
||||
Ok(())
|
||||
@@ -37,42 +25,35 @@ fn verify_dealer(deps: DepsMut<'_>, dealer: &Addr, resharing: bool) -> Result<()
|
||||
// future optimisation:
|
||||
// for a recurring dealer just let it refresh the keys without having to do all the storage operations
|
||||
pub fn try_add_dealer(
|
||||
mut deps: DepsMut<'_>,
|
||||
deps: DepsMut<'_>,
|
||||
info: MessageInfo,
|
||||
bte_key_with_proof: EncodedBTEPublicKeyWithProof,
|
||||
identity_key: String,
|
||||
announce_address: String,
|
||||
resharing: bool,
|
||||
) -> Result<Response, ContractError> {
|
||||
let epoch = CURRENT_EPOCH.load(deps.storage)?;
|
||||
check_epoch_state(deps.storage, EpochState::PublicKeySubmission { resharing })?;
|
||||
|
||||
verify_dealer(deps.branch(), &info.sender, resharing)?;
|
||||
// make sure this potential dealer actually belong to the group
|
||||
ensure_group_member(deps.as_ref(), &info.sender)?;
|
||||
|
||||
// if it was already a dealer in the past, assign the same node index
|
||||
let node_index = if let Some(prior_details) =
|
||||
dealers_storage::past_dealers().may_load(deps.storage, &info.sender)?
|
||||
{
|
||||
// since this dealer is going to become active now, remove it from the past dealers
|
||||
dealers_storage::past_dealers().replace(
|
||||
deps.storage,
|
||||
&info.sender,
|
||||
None,
|
||||
Some(&prior_details),
|
||||
)?;
|
||||
prior_details.assigned_index
|
||||
} else {
|
||||
dealers_storage::next_node_index(deps.storage)?
|
||||
};
|
||||
let node_index = get_or_assign_index(deps.storage, &info.sender)?;
|
||||
|
||||
// save the dealer into the storage
|
||||
let dealer_details = DealerDetails {
|
||||
address: info.sender.clone(),
|
||||
// save the dealer into the storage (if it hasn't already been saved)
|
||||
let dealer_details = DealerRegistrationDetails {
|
||||
bte_public_key_with_proof: bte_key_with_proof,
|
||||
ed25519_identity: identity_key,
|
||||
announce_address,
|
||||
assigned_index: node_index,
|
||||
};
|
||||
dealers_storage::current_dealers().save(deps.storage, &info.sender, &dealer_details)?;
|
||||
save_dealer_details_if_not_a_dealer(
|
||||
deps.storage,
|
||||
&info.sender,
|
||||
epoch.epoch_id,
|
||||
dealer_details,
|
||||
)?;
|
||||
|
||||
// increment the number of registered dealers
|
||||
CURRENT_EPOCH.update(deps.storage, |epoch| -> StdResult<_> {
|
||||
let mut updated_epoch = epoch;
|
||||
updated_epoch.state_progress.registered_dealers += 1;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
use crate::error::ContractError;
|
||||
use crate::Dealer;
|
||||
use cosmwasm_std::{Addr, Storage};
|
||||
use cosmwasm_std::Storage;
|
||||
use cw_storage_plus::{Key, Map, Path, PrimaryKey};
|
||||
use nym_coconut_dkg_common::dealing::{DealingMetadata, PartialContractDealing};
|
||||
use nym_coconut_dkg_common::types::{
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
// Copyright 2022-2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::dealers::storage as dealers_storage;
|
||||
use crate::dealers::storage::ensure_dealer;
|
||||
use crate::dealings::storage::{
|
||||
metadata_exists, must_read_metadata, store_metadata, StoredDealing,
|
||||
};
|
||||
use crate::epoch_state::storage::{CURRENT_EPOCH, INITIAL_REPLACEMENT_DATA};
|
||||
use crate::epoch_state::storage::CURRENT_EPOCH;
|
||||
use crate::epoch_state::utils::check_epoch_state;
|
||||
use crate::error::ContractError;
|
||||
use crate::state::storage::STATE;
|
||||
@@ -13,31 +13,25 @@ use cosmwasm_std::{Addr, DepsMut, Env, MessageInfo, Response, Storage};
|
||||
use nym_coconut_dkg_common::dealing::{
|
||||
DealingChunkInfo, DealingMetadata, PartialContractDealing, MAX_DEALING_CHUNKS,
|
||||
};
|
||||
use nym_coconut_dkg_common::types::{ChunkIndex, DealingIndex, EpochState};
|
||||
use nym_coconut_dkg_common::types::{ChunkIndex, DealingIndex, EpochId, EpochState};
|
||||
|
||||
// make sure the epoch is in the dealing exchange and the message sender is a valid dealer for this epoch
|
||||
fn ensure_permission(
|
||||
storage: &dyn Storage,
|
||||
sender: &Addr,
|
||||
current_epoch_id: EpochId,
|
||||
resharing: bool,
|
||||
) -> Result<(), ContractError> {
|
||||
check_epoch_state(storage, EpochState::DealingExchange { resharing })?;
|
||||
|
||||
// ensure the sender is a dealer
|
||||
if dealers_storage::current_dealers()
|
||||
.may_load(storage, sender)?
|
||||
.is_none()
|
||||
{
|
||||
return Err(ContractError::NotADealer);
|
||||
}
|
||||
if resharing
|
||||
&& !INITIAL_REPLACEMENT_DATA
|
||||
.load(storage)?
|
||||
.initial_dealers
|
||||
.contains(sender)
|
||||
{
|
||||
return Err(ContractError::NotAnInitialDealer);
|
||||
// ensure the sender is a dealer for this epoch
|
||||
ensure_dealer(storage, sender, current_epoch_id)?;
|
||||
|
||||
// if we're in resharing, make sure this sender has also been a dealer in the previous epoch
|
||||
if resharing {
|
||||
ensure_dealer(storage, sender, current_epoch_id.saturating_sub(1))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -48,10 +42,10 @@ pub fn try_submit_dealings_metadata(
|
||||
chunks: Vec<DealingChunkInfo>,
|
||||
resharing: bool,
|
||||
) -> Result<Response, ContractError> {
|
||||
ensure_permission(deps.storage, &info.sender, resharing)?;
|
||||
|
||||
let state = STATE.load(deps.storage)?;
|
||||
let epoch = CURRENT_EPOCH.load(deps.storage)?;
|
||||
let state = STATE.load(deps.storage)?;
|
||||
|
||||
ensure_permission(deps.storage, &info.sender, epoch.epoch_id, resharing)?;
|
||||
|
||||
// don't allow overwriting existing metadata
|
||||
if metadata_exists(deps.storage, epoch.epoch_id, &info.sender, dealing_index) {
|
||||
@@ -139,9 +133,9 @@ pub fn try_commit_dealings_chunk(
|
||||
env: Env,
|
||||
info: MessageInfo,
|
||||
chunk: PartialContractDealing,
|
||||
resharing: bool,
|
||||
) -> Result<Response, ContractError> {
|
||||
ensure_permission(deps.storage, &info.sender, resharing)?;
|
||||
// note: checking permissions is implicit as if the metadata exists,
|
||||
// the sender must have been allowed to submit it
|
||||
|
||||
let epoch = CURRENT_EPOCH.load(deps.storage)?;
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::epoch_state::storage::{CURRENT_EPOCH, INITIAL_REPLACEMENT_DATA, THRESHOLD};
|
||||
use crate::epoch_state::storage::{CURRENT_EPOCH, THRESHOLD};
|
||||
use crate::error::ContractError;
|
||||
use cosmwasm_std::Storage;
|
||||
use nym_coconut_dkg_common::types::{Epoch, InitialReplacementData};
|
||||
use nym_coconut_dkg_common::types::Epoch;
|
||||
|
||||
pub(crate) fn query_current_epoch(storage: &dyn Storage) -> Result<Epoch, ContractError> {
|
||||
CURRENT_EPOCH
|
||||
@@ -18,12 +18,6 @@ pub(crate) fn query_current_epoch_threshold(
|
||||
Ok(THRESHOLD.may_load(storage)?)
|
||||
}
|
||||
|
||||
pub(crate) fn query_initial_dealers(
|
||||
storage: &dyn Storage,
|
||||
) -> Result<Option<InitialReplacementData>, ContractError> {
|
||||
Ok(INITIAL_REPLACEMENT_DATA.may_load(storage)?)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) mod test {
|
||||
use super::*;
|
||||
|
||||
@@ -2,11 +2,7 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use cw_storage_plus::Item;
|
||||
use nym_coconut_dkg_common::types::{Epoch, InitialReplacementData};
|
||||
use nym_coconut_dkg_common::types::Epoch;
|
||||
|
||||
pub(crate) const CURRENT_EPOCH: Item<'_, Epoch> = Item::new("current_epoch");
|
||||
pub const THRESHOLD: Item<u64> = Item::new("threshold");
|
||||
|
||||
#[deprecated]
|
||||
pub const INITIAL_REPLACEMENT_DATA: Item<InitialReplacementData> =
|
||||
Item::new("initial_replacement_data");
|
||||
|
||||
@@ -1,17 +1,11 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::dealers::storage::current_dealers;
|
||||
use crate::epoch_state::storage::{CURRENT_EPOCH, INITIAL_REPLACEMENT_DATA, THRESHOLD};
|
||||
use crate::epoch_state::transactions::{
|
||||
dealers_eq_members, replacement_threshold_surpassed, reset_dkg_state,
|
||||
};
|
||||
use crate::epoch_state::utils::{check_state_completion, needs_reset, needs_resharing};
|
||||
use crate::epoch_state::storage::{CURRENT_EPOCH, THRESHOLD};
|
||||
use crate::epoch_state::utils::check_state_completion;
|
||||
use crate::error::ContractError;
|
||||
use crate::state::storage::STATE;
|
||||
use crate::verification_key_shares::storage::verified_dealers;
|
||||
use cosmwasm_std::{Addr, Deps, DepsMut, Env, Order, Response};
|
||||
use nym_coconut_dkg_common::types::{Epoch, EpochState, InitialReplacementData};
|
||||
use cosmwasm_std::{Deps, DepsMut, Env, Response};
|
||||
use nym_coconut_dkg_common::types::{Epoch, EpochState};
|
||||
|
||||
fn ensure_can_advance_state(
|
||||
deps: Deps<'_>,
|
||||
@@ -49,7 +43,7 @@ pub fn try_advance_epoch_state(deps: DepsMut<'_>, env: Env) -> Result<Response,
|
||||
// checks whether the given phase has either completed or reached its deadline
|
||||
ensure_can_advance_state(deps.as_ref(), &env, ¤t_epoch)?;
|
||||
|
||||
let next_state = match current_epoch.state.next() {
|
||||
let mut next_state = match current_epoch.state.next() {
|
||||
Some(next_state) => next_state,
|
||||
None => {
|
||||
debug_assert!(current_epoch.state.is_in_progress());
|
||||
@@ -60,89 +54,21 @@ pub fn try_advance_epoch_state(deps: DepsMut<'_>, env: Env) -> Result<Response,
|
||||
}
|
||||
};
|
||||
|
||||
// edge case: we have completed DKG with fewer than threshold number of verified keys.
|
||||
// we have no choice but to reset since no credentials can be issued anyway
|
||||
if next_state.is_in_progress() {
|
||||
let threshold = THRESHOLD.load(deps.storage)?;
|
||||
if (current_epoch.state_progress.verified_keys as u64) < threshold {
|
||||
next_state = EpochState::PublicKeySubmission { resharing: false }
|
||||
};
|
||||
}
|
||||
|
||||
// update the epoch state
|
||||
let mut next_epoch = current_epoch;
|
||||
next_epoch.state = next_state;
|
||||
CURRENT_EPOCH.save(deps.storage, &next_epoch)?;
|
||||
|
||||
Ok(Response::new())
|
||||
|
||||
//
|
||||
//
|
||||
// let next_epoch = if let Some(state) = current_epoch.state.next() {
|
||||
// // We are during DKG process
|
||||
// let mut new_state = state;
|
||||
// if let EpochState::DealingExchange { .. } = state {
|
||||
// let current_dealers = current_dealers()
|
||||
// .keys(deps.storage, None, None, Order::Ascending)
|
||||
// .collect::<Result<Vec<Addr>, _>>()?;
|
||||
// let group_members =
|
||||
// STATE
|
||||
// .load(deps.storage)?
|
||||
// .group_addr
|
||||
// .list_members(&deps.querier, None, None)?;
|
||||
// if current_dealers.len() < group_members.len() {
|
||||
// // If not all group members registered yet, we just stay in the same state until
|
||||
// // they either register or they get kicked out of the group
|
||||
// new_state = current_epoch.state;
|
||||
// } else {
|
||||
// // note: ceiling in integer division can be achieved via q = (x + y - 1) / y;
|
||||
// let threshold = (2 * current_dealers.len() as u64 + 3 - 1) / 3;
|
||||
// THRESHOLD.save(deps.storage, &threshold)?;
|
||||
// }
|
||||
// };
|
||||
// Epoch::new(
|
||||
// new_state,
|
||||
// current_epoch.epoch_id,
|
||||
// current_epoch.time_configuration,
|
||||
// env.block.time,
|
||||
// )
|
||||
// } else if dealers_eq_members(&deps)? {
|
||||
// // The dealer set hasn't changed, so we only extend the finish timestamp
|
||||
// // The epoch remains the same, as we use it as key for storing VKs
|
||||
//
|
||||
// // TODO: change that behaviour in the following PR
|
||||
// Epoch::new(
|
||||
// current_epoch.state,
|
||||
// current_epoch.epoch_id,
|
||||
// current_epoch.time_configuration,
|
||||
// env.block.time,
|
||||
// )
|
||||
// } else {
|
||||
// // Dealer set changed, we need to redo DKG...
|
||||
// let state = if replacement_threshold_surpassed(&deps)? {
|
||||
// // ... in reset mode
|
||||
// INITIAL_REPLACEMENT_DATA.remove(deps.storage);
|
||||
// EpochState::PublicKeySubmission { resharing: false }
|
||||
// } else {
|
||||
// // ... in reshare mode
|
||||
// if INITIAL_REPLACEMENT_DATA.may_load(deps.storage)?.is_some() {
|
||||
// INITIAL_REPLACEMENT_DATA.update::<_, ContractError>(deps.storage, |mut data| {
|
||||
// // TODO: FIXME: for second reshare the added set of dealers won't be allowed to participate
|
||||
// data.initial_height = env.block.height;
|
||||
// Ok(data)
|
||||
// })?;
|
||||
// } else {
|
||||
// let replacement_data = InitialReplacementData {
|
||||
// initial_dealers: verified_dealers(deps.storage)?,
|
||||
// initial_height: env.block.height,
|
||||
// };
|
||||
// INITIAL_REPLACEMENT_DATA.save(deps.storage, &replacement_data)?;
|
||||
// }
|
||||
//
|
||||
// EpochState::PublicKeySubmission { resharing: true }
|
||||
// };
|
||||
// reset_dkg_state(deps.storage)?;
|
||||
// Epoch::new(
|
||||
// state,
|
||||
// current_epoch.epoch_id + 1,
|
||||
// current_epoch.time_configuration,
|
||||
// env.block.time,
|
||||
// )
|
||||
// };
|
||||
// CURRENT_EPOCH.save(deps.storage, &next_epoch)?;
|
||||
//
|
||||
// Ok(Response::default())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@@ -1,14 +1,10 @@
|
||||
// Copyright 2022-2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::dealers::storage::{current_dealers, past_dealers};
|
||||
use crate::epoch_state::storage::{CURRENT_EPOCH, THRESHOLD};
|
||||
use crate::epoch_state::utils::check_epoch_state;
|
||||
use crate::error::ContractError;
|
||||
use crate::state::storage::{DKG_ADMIN, STATE};
|
||||
use crate::verification_key_shares::storage::verified_dealers;
|
||||
use cosmwasm_std::{Addr, Deps, DepsMut, Env, MessageInfo, Order, Response, Storage};
|
||||
use cw4::Member;
|
||||
use crate::state::storage::DKG_ADMIN;
|
||||
use cosmwasm_std::{DepsMut, Env, MessageInfo, Order, Response, Storage};
|
||||
use nym_coconut_dkg_common::types::{Epoch, EpochState};
|
||||
|
||||
pub use advance_epoch_state::try_advance_epoch_state;
|
||||
@@ -18,66 +14,19 @@ pub mod advance_epoch_state;
|
||||
fn reset_dkg_state(storage: &mut dyn Storage) -> Result<(), ContractError> {
|
||||
THRESHOLD.remove(storage);
|
||||
|
||||
// TODO: unbounded query. to be removed be preserving dealer details and changing storage structure
|
||||
let dealers: Vec<_> = current_dealers()
|
||||
.keys(storage, None, None, Order::Ascending)
|
||||
.collect::<Result<_, _>>()?;
|
||||
|
||||
for dealer_addr in dealers {
|
||||
let details = current_dealers().load(storage, &dealer_addr)?;
|
||||
current_dealers().remove(storage, &dealer_addr)?;
|
||||
past_dealers().save(storage, &dealer_addr, &details)?;
|
||||
}
|
||||
// // TODO: unbounded query. to be removed be preserving dealer details and changing storage structure
|
||||
// let dealers: Vec<_> = current_dealers()
|
||||
// .keys(storage, None, None, Order::Ascending)
|
||||
// .collect::<Result<_, _>>()?;
|
||||
//
|
||||
// for dealer_addr in dealers {
|
||||
// let details = current_dealers().load(storage, &dealer_addr)?;
|
||||
// current_dealers().remove(storage, &dealer_addr)?;
|
||||
// past_dealers().save(storage, &dealer_addr, &details)?;
|
||||
// }
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn dealers_still_active(
|
||||
deps: &Deps<'_>,
|
||||
dealers: impl Iterator<Item = Addr>,
|
||||
) -> Result<usize, ContractError> {
|
||||
let state = STATE.load(deps.storage)?;
|
||||
let mut still_active = 0;
|
||||
for dealer_addr in dealers {
|
||||
if state
|
||||
.group_addr
|
||||
.is_voting_member(&deps.querier, &dealer_addr, None)?
|
||||
.is_some()
|
||||
{
|
||||
still_active += 1;
|
||||
}
|
||||
}
|
||||
Ok(still_active)
|
||||
}
|
||||
|
||||
#[deprecated]
|
||||
fn dealers_eq_members(deps: &DepsMut<'_>) -> Result<bool, ContractError> {
|
||||
let verified_dealers = verified_dealers(deps.storage)?;
|
||||
let all_dealers = verified_dealers.len();
|
||||
let dealers_still_active = dealers_still_active(&deps.as_ref(), verified_dealers.into_iter())?;
|
||||
let group_members = STATE
|
||||
.load(deps.storage)?
|
||||
.group_addr
|
||||
.list_members(&deps.querier, None, None)?
|
||||
.len();
|
||||
|
||||
Ok(dealers_still_active == all_dealers && all_dealers == group_members)
|
||||
}
|
||||
|
||||
fn replacement_threshold_surpassed(deps: &DepsMut<'_>) -> Result<bool, ContractError> {
|
||||
let threshold = THRESHOLD.load(deps.storage)? as usize;
|
||||
let initial_dealers = verified_dealers(deps.storage)?;
|
||||
if initial_dealers.is_empty() {
|
||||
// possibly failed DKG, just reset and start again
|
||||
return Ok(true);
|
||||
}
|
||||
let initial_dealer_count = initial_dealers.len();
|
||||
let replacement_threshold = threshold - (initial_dealers.len() + 2 - 1) / 2 + 1;
|
||||
let removed_dealer_count =
|
||||
initial_dealer_count - dealers_still_active(&deps.as_ref(), initial_dealers.into_iter())?;
|
||||
|
||||
Ok(removed_dealer_count >= replacement_threshold)
|
||||
}
|
||||
|
||||
pub(crate) fn try_initiate_dkg(
|
||||
deps: DepsMut<'_>,
|
||||
env: Env,
|
||||
@@ -99,29 +48,6 @@ pub(crate) fn try_initiate_dkg(
|
||||
Ok(Response::default())
|
||||
}
|
||||
|
||||
pub(crate) fn try_surpassed_threshold(
|
||||
deps: DepsMut<'_>,
|
||||
env: Env,
|
||||
) -> Result<Response, ContractError> {
|
||||
check_epoch_state(deps.storage, EpochState::InProgress)?;
|
||||
|
||||
let threshold = THRESHOLD.load(deps.storage)?;
|
||||
let dealers = verified_dealers(deps.storage)?;
|
||||
if dealers_still_active(&deps.as_ref(), dealers.into_iter())? < threshold as usize {
|
||||
reset_dkg_state(deps.storage)?;
|
||||
CURRENT_EPOCH.update::<_, ContractError>(deps.storage, |epoch| {
|
||||
Ok(Epoch::new(
|
||||
EpochState::default(),
|
||||
epoch.epoch_id + 1,
|
||||
epoch.time_configuration,
|
||||
env.block.time,
|
||||
))
|
||||
})?;
|
||||
}
|
||||
|
||||
Ok(Response::default())
|
||||
}
|
||||
|
||||
pub(crate) fn try_trigger_reset(
|
||||
deps: DepsMut<'_>,
|
||||
env: Env,
|
||||
|
||||
@@ -4,31 +4,9 @@
|
||||
use crate::epoch_state::storage::CURRENT_EPOCH;
|
||||
use crate::error::ContractError;
|
||||
use crate::state::storage::STATE;
|
||||
use crate::verification_key_shares::storage::{dealers, verified_dealers};
|
||||
use cosmwasm_std::{Addr, Deps, StdResult, Storage};
|
||||
use cw4::Member;
|
||||
use cosmwasm_std::Storage;
|
||||
use nym_coconut_dkg_common::types::{Epoch, EpochState};
|
||||
|
||||
fn all_group_members(deps: &Deps) -> Result<Vec<Member>, ContractError> {
|
||||
// the maximum limit for members queries is 30.
|
||||
// if we're ever thinking of going beyond it, we should fix it properly
|
||||
// by the DKG contract owning the group contract (i.e. init inside init)
|
||||
// and proxying all member changes and thus memoizing the members.
|
||||
// alternatively by adding hooks to the contract to inform us about any changes
|
||||
let members =
|
||||
STATE
|
||||
.load(deps.storage)?
|
||||
.group_addr
|
||||
.list_members(&deps.querier, None, Some(30))?;
|
||||
|
||||
// if we're at the limit...
|
||||
if members.len() == 30 {
|
||||
return Err(ContractError::PossiblyIncompleteGroupMembersQuery);
|
||||
}
|
||||
|
||||
Ok(members)
|
||||
}
|
||||
|
||||
// check if we completed the state, so we could short circuit the deadline
|
||||
pub(crate) fn check_state_completion(
|
||||
storage: &dyn Storage,
|
||||
@@ -65,57 +43,6 @@ pub(crate) fn check_state_completion(
|
||||
}
|
||||
}
|
||||
|
||||
/// Checks whether the DKG needs to undergo full reset.
|
||||
/// This is determined by whether the initial set of validator changed by more than a threshold number
|
||||
/// of parties joining or leaving.
|
||||
pub(crate) fn needs_reset(deps: Deps) -> Result<bool, ContractError> {
|
||||
let current_state = CURRENT_EPOCH.load(deps.storage)?.state;
|
||||
|
||||
// there is a theoretical edge case where we add/remove an extra member during an in-progress exchange
|
||||
// thus possibly needing reset immediately after it's done. an optimization would be to just scrap it and start it over
|
||||
// but since members are added manually, we don't have to worry about it too much for now.
|
||||
if !current_state.is_in_progress() {
|
||||
return Err(ContractError::CantResetDuringExchange);
|
||||
}
|
||||
|
||||
let group_members = all_group_members(&deps)?;
|
||||
|
||||
// below threshold => must reset since we can't do anything
|
||||
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Checks whether the DKG needs to undergo resharing.
|
||||
/// This is determined by whether any new group members has joined the associated group contract
|
||||
pub(crate) fn needs_resharing(deps: Deps) -> Result<bool, ContractError> {
|
||||
let current_state = CURRENT_EPOCH.load(deps.storage)?.state;
|
||||
|
||||
// there is a theoretical edge case where we add an extra member during an in-progress exchange
|
||||
// thus needing resharing immediately after it's done. an optimization would be to just scrap it and start it over
|
||||
// but since members are added manually, we don't have to worry about it too much for now.
|
||||
if !current_state.is_in_progress() {
|
||||
return Err(ContractError::CantReshareDuringExchange);
|
||||
}
|
||||
|
||||
// TODO: we need cw4 hooks here to resolve those expensive queries
|
||||
let group_members = all_group_members(&deps)?;
|
||||
let epoch_dealers = dealers(deps.storage)?;
|
||||
|
||||
// if somebody has been a dealer, but hasn't been verified, tough luck
|
||||
// we only allow for resharing for new members
|
||||
|
||||
// check if we have any new members
|
||||
for member in group_members {
|
||||
if !epoch_dealers.contains_key(&Addr::unchecked(member.addr)) {
|
||||
return Ok(true);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: something about reset here
|
||||
|
||||
Ok(false)
|
||||
}
|
||||
|
||||
pub(crate) fn check_epoch_state(
|
||||
storage: &dyn Storage,
|
||||
against: EpochState,
|
||||
|
||||
@@ -45,8 +45,8 @@ pub enum ContractError {
|
||||
expected_state: String,
|
||||
},
|
||||
|
||||
#[error("This sender is not a dealer for the current epoch")]
|
||||
NotADealer,
|
||||
#[error("This sender is not a dealer for epoch {epoch_id}")]
|
||||
NotADealer { epoch_id: EpochId },
|
||||
|
||||
#[error("This sender is not a dealer for the current resharing epoch")]
|
||||
NotAnInitialDealer,
|
||||
|
||||
@@ -2,16 +2,13 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::constants::{VK_SHARES_EPOCH_ID_IDX_NAMESPACE, VK_SHARES_PK_NAMESPACE};
|
||||
use crate::epoch_state::storage::CURRENT_EPOCH;
|
||||
use crate::error::ContractError;
|
||||
use cosmwasm_std::{Addr, Order, StdResult, Storage};
|
||||
use cosmwasm_std::Addr;
|
||||
use cw_storage_plus::{Index, IndexList, IndexedMap, MultiIndex};
|
||||
use nym_coconut_dkg_common::types::EpochId;
|
||||
use nym_coconut_dkg_common::verification_key::ContractVKShare;
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub(crate) const VERIFICATION_KEY_SHARES_PAGE_MAX_LIMIT: u32 = 75;
|
||||
pub(crate) const VERIFICATION_KEY_SHARES_PAGE_DEFAULT_LIMIT: u32 = 50;
|
||||
pub(crate) const VERIFICATION_KEY_SHARES_PAGE_MAX_LIMIT: u32 = 30;
|
||||
pub(crate) const VERIFICATION_KEY_SHARES_PAGE_DEFAULT_LIMIT: u32 = 10;
|
||||
|
||||
type VKShareKey<'a> = (&'a Addr, EpochId);
|
||||
|
||||
@@ -36,40 +33,3 @@ pub(crate) fn vk_shares<'a>() -> IndexedMap<'a, VKShareKey<'a>, ContractVKShare,
|
||||
};
|
||||
IndexedMap::new(VK_SHARES_PK_NAMESPACE, indexes)
|
||||
}
|
||||
|
||||
// TODO: this is a ticking time bomb and will cause us headache when we start running out of gas... again...
|
||||
// not sure how to fix it yet...
|
||||
// maybe by completely removing it by relying on cw4 hooks?
|
||||
#[deprecated]
|
||||
pub(crate) fn verified_dealers(storage: &dyn Storage) -> Result<Vec<Addr>, ContractError> {
|
||||
let epoch_id = CURRENT_EPOCH.load(storage)?.epoch_id;
|
||||
Ok(vk_shares()
|
||||
.idx
|
||||
.epoch_id
|
||||
.prefix(epoch_id)
|
||||
.range(storage, None, None, Order::Ascending)
|
||||
.flatten()
|
||||
.filter_map(|(_, share)| {
|
||||
if share.verified {
|
||||
Some(share.owner)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect())
|
||||
}
|
||||
|
||||
// TODO: this is a ticking time bomb and will cause us headache when we start running out of gas... again...
|
||||
// not sure how to fix it yet...
|
||||
// maybe by completely removing it by relying on cw4 hooks?
|
||||
pub(crate) fn dealers(storage: &dyn Storage) -> Result<HashMap<Addr, bool>, ContractError> {
|
||||
let epoch_id = CURRENT_EPOCH.load(storage)?.epoch_id;
|
||||
|
||||
Ok(vk_shares()
|
||||
.idx
|
||||
.epoch_id
|
||||
.prefix(epoch_id)
|
||||
.range(storage, None, None, Order::Ascending)
|
||||
.map(|maybe_share| maybe_share.map(|(_, v)| (v.owner, v.verified)))
|
||||
.collect::<StdResult<_>>()?)
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::constants::BLOCK_TIME_FOR_VERIFICATION_SECS;
|
||||
use crate::dealers::storage as dealers_storage;
|
||||
use crate::dealers::storage::get_dealer_details;
|
||||
use crate::epoch_state::storage::CURRENT_EPOCH;
|
||||
use crate::epoch_state::utils::check_epoch_state;
|
||||
use crate::error::ContractError;
|
||||
@@ -25,11 +25,9 @@ pub fn try_commit_verification_key_share(
|
||||
deps.storage,
|
||||
EpochState::VerificationKeySubmission { resharing },
|
||||
)?;
|
||||
// ensure the sender is a dealer
|
||||
let details = dealers_storage::current_dealers()
|
||||
.load(deps.storage, &info.sender)
|
||||
.map_err(|_| ContractError::NotADealer)?;
|
||||
let epoch_id = CURRENT_EPOCH.load(deps.storage)?.epoch_id;
|
||||
|
||||
let details = get_dealer_details(deps.storage, &info.sender, epoch_id)?;
|
||||
if vk_shares()
|
||||
.may_load(deps.storage, (&info.sender, epoch_id))?
|
||||
.is_some()
|
||||
|
||||
Reference in New Issue
Block a user