contract changes
This commit is contained in:
@@ -1,10 +1,7 @@
|
||||
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::types::{
|
||||
DealingIndex, EncodedBTEPublicKeyWithProof, EpochId, NodeIndex, PartialContractDealing,
|
||||
PartialContractDealingData,
|
||||
};
|
||||
use crate::types::{EncodedBTEPublicKeyWithProof, NodeIndex};
|
||||
use cosmwasm_schema::cw_serde;
|
||||
use cosmwasm_std::Addr;
|
||||
|
||||
@@ -68,53 +65,3 @@ impl PagedDealerResponse {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cw_serde]
|
||||
pub struct DealingResponse {
|
||||
pub epoch_id: EpochId,
|
||||
|
||||
pub dealer: Addr,
|
||||
|
||||
pub dealing_index: DealingIndex,
|
||||
|
||||
pub dealing: Option<PartialContractDealingData>,
|
||||
}
|
||||
|
||||
#[cw_serde]
|
||||
pub struct DealingStatusResponse {
|
||||
pub epoch_id: EpochId,
|
||||
|
||||
pub dealer: Addr,
|
||||
|
||||
pub dealing_index: DealingIndex,
|
||||
|
||||
pub dealing_submitted: bool,
|
||||
}
|
||||
|
||||
#[cw_serde]
|
||||
pub struct PagedDealingsResponse {
|
||||
pub epoch_id: EpochId,
|
||||
|
||||
pub dealer: Addr,
|
||||
|
||||
pub dealings: Vec<PartialContractDealing>,
|
||||
|
||||
/// Field indicating paging information for the following queries if the caller wishes to get further entries.
|
||||
pub start_next_after: Option<DealingIndex>,
|
||||
}
|
||||
|
||||
impl PagedDealingsResponse {
|
||||
pub fn new(
|
||||
epoch_id: EpochId,
|
||||
dealer: Addr,
|
||||
dealings: Vec<PartialContractDealing>,
|
||||
start_next_after: Option<DealingIndex>,
|
||||
) -> Self {
|
||||
PagedDealingsResponse {
|
||||
epoch_id,
|
||||
dealer,
|
||||
dealings,
|
||||
start_next_after,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,198 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::types::{ChunkIndex, DealingIndex, EpochId, PartialContractDealingData};
|
||||
use cosmwasm_schema::cw_serde;
|
||||
use cosmwasm_std::Addr;
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
/// Defines the maximum size of a dealing chunk. Currently set to 2kB
|
||||
pub const MAX_DEALING_CHUNK_SIZE: usize = 2048;
|
||||
|
||||
/// Defines the maximum size of a full dealing.
|
||||
/// Currently set to 100kB (which is enough for a dealing created for 100 parties)
|
||||
pub const MAX_DEALING_SIZE: usize = 102400;
|
||||
|
||||
pub const MAX_DEALING_CHUNKS: usize = MAX_DEALING_SIZE / MAX_DEALING_CHUNK_SIZE;
|
||||
|
||||
// 2 public attributes, 2 private attributes, 1 fixed for coconut credential
|
||||
pub const DEFAULT_DEALINGS: usize = 2 + 2 + 1;
|
||||
|
||||
#[cw_serde]
|
||||
pub struct DealingChunkInfo {
|
||||
pub size: usize,
|
||||
}
|
||||
|
||||
impl DealingChunkInfo {
|
||||
pub fn new(size: usize) -> Self {
|
||||
DealingChunkInfo { size }
|
||||
}
|
||||
|
||||
pub fn construct(dealing_len: usize, chunk_size: usize) -> Vec<Self> {
|
||||
let (full_chunks, overflow) = (dealing_len / chunk_size, dealing_len % chunk_size);
|
||||
|
||||
let mut chunks = Vec::new();
|
||||
for _ in 0..full_chunks {
|
||||
chunks.push(DealingChunkInfo::new(chunk_size));
|
||||
}
|
||||
|
||||
if overflow != 0 {
|
||||
chunks.push(DealingChunkInfo::new(overflow));
|
||||
}
|
||||
|
||||
chunks
|
||||
}
|
||||
}
|
||||
|
||||
#[cw_serde]
|
||||
pub struct SubmittedChunk {
|
||||
pub info: DealingChunkInfo,
|
||||
|
||||
// this field is updated by the contract itself to indicate when this particular chunk has been received
|
||||
pub submission_height: Option<u64>,
|
||||
}
|
||||
|
||||
impl From<DealingChunkInfo> for SubmittedChunk {
|
||||
fn from(value: DealingChunkInfo) -> Self {
|
||||
SubmittedChunk::new(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl SubmittedChunk {
|
||||
pub fn new(info: DealingChunkInfo) -> Self {
|
||||
SubmittedChunk {
|
||||
info,
|
||||
submission_height: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cw_serde]
|
||||
pub struct DealingMetadata {
|
||||
pub dealing_index: DealingIndex,
|
||||
|
||||
pub submitted_chunks: BTreeMap<ChunkIndex, SubmittedChunk>,
|
||||
}
|
||||
|
||||
impl DealingMetadata {
|
||||
pub fn new(dealing_index: DealingIndex, chunks: Vec<DealingChunkInfo>) -> Self {
|
||||
DealingMetadata {
|
||||
dealing_index,
|
||||
submitted_chunks: chunks
|
||||
.into_iter()
|
||||
.enumerate()
|
||||
.map(|(id, chunk)| (id as ChunkIndex, chunk.into()))
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_complete(&self) -> bool {
|
||||
self.submitted_chunks
|
||||
.values()
|
||||
.all(|c| c.submission_height.is_some())
|
||||
}
|
||||
|
||||
pub fn total_size(&self) -> usize {
|
||||
self.submitted_chunks.values().map(|c| c.info.size).sum()
|
||||
}
|
||||
}
|
||||
|
||||
#[cw_serde]
|
||||
pub struct PartialContractDealing {
|
||||
pub dealing_index: DealingIndex,
|
||||
pub chunk_index: ChunkIndex,
|
||||
pub data: PartialContractDealingData,
|
||||
}
|
||||
|
||||
impl PartialContractDealing {
|
||||
pub fn new(
|
||||
dealing_index: DealingIndex,
|
||||
chunk_index: ChunkIndex,
|
||||
data: PartialContractDealingData,
|
||||
) -> Self {
|
||||
PartialContractDealing {
|
||||
dealing_index,
|
||||
chunk_index,
|
||||
data,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cw_serde]
|
||||
pub struct DealingMetadataResponse {
|
||||
pub epoch_id: EpochId,
|
||||
|
||||
pub dealer: Addr,
|
||||
|
||||
pub dealing_index: DealingIndex,
|
||||
|
||||
pub metadata: Option<DealingMetadata>,
|
||||
}
|
||||
|
||||
#[cw_serde]
|
||||
pub struct DealingChunkResponse {
|
||||
pub epoch_id: EpochId,
|
||||
|
||||
pub dealer: Addr,
|
||||
|
||||
pub dealing_index: DealingIndex,
|
||||
|
||||
pub chunk_index: ChunkIndex,
|
||||
|
||||
pub chunk: Option<PartialContractDealingData>,
|
||||
}
|
||||
|
||||
#[cw_serde]
|
||||
pub struct DealingChunkStatusResponse {
|
||||
pub epoch_id: EpochId,
|
||||
|
||||
pub dealer: Addr,
|
||||
|
||||
pub dealing_index: DealingIndex,
|
||||
|
||||
pub chunk_index: ChunkIndex,
|
||||
|
||||
pub submission_height: Option<u64>,
|
||||
}
|
||||
|
||||
#[cw_serde]
|
||||
pub struct DealingStatusResponse {
|
||||
pub epoch_id: EpochId,
|
||||
|
||||
pub dealer: Addr,
|
||||
|
||||
pub dealing_index: DealingIndex,
|
||||
|
||||
pub full_dealing_submitted: bool,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn chunking_dealings() {
|
||||
const CHUNK_SIZE: usize = 512;
|
||||
|
||||
let test_cases = [
|
||||
(CHUNK_SIZE - 10, CHUNK_SIZE, 1),
|
||||
(CHUNK_SIZE, CHUNK_SIZE, 1),
|
||||
(CHUNK_SIZE + 10, CHUNK_SIZE, 2),
|
||||
(CHUNK_SIZE * 2, CHUNK_SIZE, 2),
|
||||
(CHUNK_SIZE * 2 + 1, CHUNK_SIZE, 3),
|
||||
(CHUNK_SIZE * 10 + 42, CHUNK_SIZE, 11),
|
||||
];
|
||||
|
||||
for (dealing_len, chunk_size, expected_chunks) in test_cases {
|
||||
let chunks = DealingChunkInfo::construct(dealing_len, chunk_size);
|
||||
assert_eq!(expected_chunks, chunks.len());
|
||||
assert_eq!(dealing_len, chunks.iter().map(|c| c.size).sum::<usize>());
|
||||
|
||||
let mut expected_last = dealing_len % chunk_size;
|
||||
if expected_last == 0 {
|
||||
expected_last = chunk_size;
|
||||
}
|
||||
assert_eq!(chunks.last().unwrap().size, expected_last);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,8 @@
|
||||
// Copyright 2022-2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
pub mod dealer;
|
||||
pub mod dealing;
|
||||
pub mod event_attributes;
|
||||
pub mod msg;
|
||||
pub mod types;
|
||||
|
||||
@@ -1,23 +1,24 @@
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// Copyright 2022-2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::dealing::{DealingChunkInfo, PartialContractDealing};
|
||||
use crate::types::{
|
||||
DealingIndex, EncodedBTEPublicKeyWithProof, EpochId, PartialContractDealing, TimeConfiguration,
|
||||
ChunkIndex, DealingIndex, EncodedBTEPublicKeyWithProof, EpochId, TimeConfiguration,
|
||||
};
|
||||
use crate::verification_key::VerificationKeyShare;
|
||||
use contracts_common::IdentityKey;
|
||||
use cosmwasm_schema::cw_serde;
|
||||
use cosmwasm_std::Addr;
|
||||
|
||||
#[cfg(feature = "schema")]
|
||||
use crate::{
|
||||
dealer::{
|
||||
DealerDetailsResponse, DealingResponse, DealingStatusResponse, PagedDealerResponse,
|
||||
PagedDealingsResponse,
|
||||
dealer::{DealerDetailsResponse, PagedDealerResponse},
|
||||
dealing::{
|
||||
DealingChunkResponse, DealingChunkStatusResponse, DealingMetadataResponse,
|
||||
DealingStatusResponse,
|
||||
},
|
||||
types::{Epoch, InitialReplacementData, State},
|
||||
verification_key::{PagedVKSharesResponse, VkShareResponse},
|
||||
};
|
||||
use contracts_common::IdentityKey;
|
||||
#[cfg(feature = "schema")]
|
||||
use cosmwasm_schema::QueryResponses;
|
||||
|
||||
@@ -44,8 +45,14 @@ pub enum ExecuteMsg {
|
||||
resharing: bool,
|
||||
},
|
||||
|
||||
CommitDealing {
|
||||
dealing: PartialContractDealing,
|
||||
CommitDealingsMetadata {
|
||||
dealing_index: DealingIndex,
|
||||
chunks: Vec<DealingChunkInfo>,
|
||||
resharing: bool,
|
||||
},
|
||||
|
||||
CommitDealingsChunk {
|
||||
chunk: PartialContractDealing,
|
||||
resharing: bool,
|
||||
},
|
||||
|
||||
@@ -55,8 +62,7 @@ pub enum ExecuteMsg {
|
||||
},
|
||||
|
||||
VerifyVerificationKeyShare {
|
||||
// TODO: this should be using a String...
|
||||
owner: Addr,
|
||||
owner: String,
|
||||
resharing: bool,
|
||||
},
|
||||
|
||||
@@ -95,6 +101,13 @@ pub enum QueryMsg {
|
||||
start_after: Option<String>,
|
||||
},
|
||||
|
||||
#[cfg_attr(feature = "schema", returns(DealingMetadataResponse))]
|
||||
GetDealingsMetadata {
|
||||
epoch_id: EpochId,
|
||||
dealer: String,
|
||||
dealing_index: DealingIndex,
|
||||
},
|
||||
|
||||
#[cfg_attr(feature = "schema", returns(DealingStatusResponse))]
|
||||
GetDealingStatus {
|
||||
epoch_id: EpochId,
|
||||
@@ -102,19 +115,20 @@ pub enum QueryMsg {
|
||||
dealing_index: DealingIndex,
|
||||
},
|
||||
|
||||
#[cfg_attr(feature = "schema", returns(DealingResponse))]
|
||||
GetDealing {
|
||||
#[cfg_attr(feature = "schema", returns(DealingChunkStatusResponse))]
|
||||
GetDealingChunkStatus {
|
||||
epoch_id: EpochId,
|
||||
dealer: String,
|
||||
dealing_index: DealingIndex,
|
||||
chunk_index: ChunkIndex,
|
||||
},
|
||||
|
||||
#[cfg_attr(feature = "schema", returns(PagedDealingsResponse))]
|
||||
GetDealings {
|
||||
#[cfg_attr(feature = "schema", returns(DealingChunkResponse))]
|
||||
GetDealingChunk {
|
||||
epoch_id: EpochId,
|
||||
dealer: String,
|
||||
limit: Option<u32>,
|
||||
start_after: Option<DealingIndex>,
|
||||
dealing_index: DealingIndex,
|
||||
chunk_index: ChunkIndex,
|
||||
},
|
||||
|
||||
#[cfg_attr(feature = "schema", returns(VkShareResponse))]
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use cosmwasm_schema::cw_serde;
|
||||
use std::collections::BTreeMap;
|
||||
use std::fmt::{Display, Formatter};
|
||||
use std::str::FromStr;
|
||||
|
||||
@@ -22,102 +21,6 @@ pub type DealingIndex = u32;
|
||||
pub type ChunkIndex = u16;
|
||||
pub type PartialContractDealingData = ContractSafeBytes;
|
||||
|
||||
/// Defines the maximum size of a dealing chunk. Currently set to 2kB
|
||||
pub const MAX_DEALING_CHUNK_SIZE: usize = 2048;
|
||||
|
||||
/// Defines the maximum size of a full dealing.
|
||||
/// Currently set to 100kB (which is enough for a dealing created for 100 parties)
|
||||
pub const MAX_DEALING_SIZE: usize = 102400;
|
||||
|
||||
pub const MAX_DEALING_CHUNKS: usize = MAX_DEALING_SIZE / MAX_DEALING_CHUNK_SIZE;
|
||||
|
||||
// 2 public attributes, 2 private attributes, 1 fixed for coconut credential
|
||||
pub const DEFAULT_DEALINGS: usize = 2 + 2 + 1;
|
||||
|
||||
#[cw_serde]
|
||||
pub struct SubmittedChunk {
|
||||
pub size: usize,
|
||||
|
||||
// this field is updated by the contract itself to indicate when this particular chunk has been received
|
||||
pub submission_height: Option<u64>,
|
||||
}
|
||||
|
||||
impl SubmittedChunk {
|
||||
pub fn new(size: usize) -> Self {
|
||||
SubmittedChunk {
|
||||
size,
|
||||
submission_height: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cw_serde]
|
||||
pub struct DealingMetadata {
|
||||
pub dealing_index: DealingIndex,
|
||||
|
||||
pub submitted_chunks: BTreeMap<ChunkIndex, SubmittedChunk>,
|
||||
}
|
||||
|
||||
impl DealingMetadata {
|
||||
pub fn new(dealing_index: DealingIndex, dealing_len: usize, chunk_size: usize) -> Self {
|
||||
let (full_chunks, overflow) = (dealing_len / chunk_size, dealing_len % chunk_size);
|
||||
|
||||
let mut submitted_chunks = BTreeMap::new();
|
||||
for id in 0..full_chunks {
|
||||
submitted_chunks.insert(id as ChunkIndex, SubmittedChunk::new(chunk_size));
|
||||
}
|
||||
|
||||
if overflow != 0 {
|
||||
submitted_chunks.insert(full_chunks as ChunkIndex, SubmittedChunk::new(overflow));
|
||||
}
|
||||
|
||||
DealingMetadata {
|
||||
dealing_index,
|
||||
submitted_chunks,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_complete(&self) -> bool {
|
||||
self.submitted_chunks
|
||||
.values()
|
||||
.all(|c| c.submission_height.is_some())
|
||||
}
|
||||
|
||||
pub fn total_size(&self) -> usize {
|
||||
self.submitted_chunks.values().map(|c| c.size).sum()
|
||||
}
|
||||
}
|
||||
|
||||
#[cw_serde]
|
||||
pub struct PartialContractDealing {
|
||||
pub dealing_index: DealingIndex,
|
||||
pub chunk_index: ChunkIndex,
|
||||
pub data: PartialContractDealingData,
|
||||
}
|
||||
|
||||
impl PartialContractDealing {
|
||||
pub fn new(
|
||||
dealing_index: DealingIndex,
|
||||
chunk_index: ChunkIndex,
|
||||
data: PartialContractDealingData,
|
||||
) -> Self {
|
||||
PartialContractDealing {
|
||||
dealing_index,
|
||||
chunk_index,
|
||||
data,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// impl From<(DealingIndex, ContractDealing)> for PartialContractDealing {
|
||||
// fn from(value: (DealingIndex, ContractDealing)) -> Self {
|
||||
// PartialContractDealing {
|
||||
// dealing_index: value.0,
|
||||
// data: value.1,
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
#[cw_serde]
|
||||
pub struct InitialReplacementData {
|
||||
pub initial_dealers: Vec<Addr>,
|
||||
@@ -350,37 +253,3 @@ impl EpochState {
|
||||
*self == EpochState::InProgress
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn dealing_metadata() {
|
||||
const CHUNK_SIZE: usize = 512;
|
||||
|
||||
let test_cases = [
|
||||
(CHUNK_SIZE - 10, CHUNK_SIZE, 1),
|
||||
(CHUNK_SIZE, CHUNK_SIZE, 1),
|
||||
(CHUNK_SIZE + 10, CHUNK_SIZE, 2),
|
||||
(CHUNK_SIZE * 2, CHUNK_SIZE, 2),
|
||||
(CHUNK_SIZE * 2 + 1, CHUNK_SIZE, 3),
|
||||
(CHUNK_SIZE * 10 + 42, CHUNK_SIZE, 11),
|
||||
];
|
||||
|
||||
for (dealing_len, chunk_size, expected_chunks) in test_cases {
|
||||
let meta = DealingMetadata::new(42, dealing_len, chunk_size);
|
||||
assert_eq!(expected_chunks, meta.submitted_chunks.len());
|
||||
assert_eq!(dealing_len, meta.total_size());
|
||||
|
||||
let mut expected_last = dealing_len % chunk_size;
|
||||
if expected_last == 0 {
|
||||
expected_last = chunk_size;
|
||||
}
|
||||
assert_eq!(
|
||||
meta.submitted_chunks.last_key_value().unwrap().1.size,
|
||||
expected_last
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,7 +43,10 @@ pub fn to_cosmos_msg(
|
||||
multisig_addr: String,
|
||||
expiration_time: Timestamp,
|
||||
) -> StdResult<CosmosMsg> {
|
||||
let verify_vk_share_req = ExecuteMsg::VerifyVerificationKeyShare { owner, resharing };
|
||||
let verify_vk_share_req = ExecuteMsg::VerifyVerificationKeyShare {
|
||||
owner: owner.to_string(),
|
||||
resharing,
|
||||
};
|
||||
let verify_vk_share_msg = CosmosMsg::Wasm(WasmMsg::Execute {
|
||||
contract_addr: coconut_dkg_addr,
|
||||
msg: to_binary(&verify_vk_share_req)?,
|
||||
@@ -67,7 +70,7 @@ pub fn to_cosmos_msg(
|
||||
// DKG SAFETY:
|
||||
// each legit verification proposal will only contain a single execute msg,
|
||||
// if they have more than one, we can safely ignore it
|
||||
pub fn owner_from_cosmos_msgs(msgs: &[CosmosMsg]) -> Option<Addr> {
|
||||
pub fn owner_from_cosmos_msgs(msgs: &[CosmosMsg]) -> Option<String> {
|
||||
if msgs.len() != 1 {
|
||||
return None;
|
||||
}
|
||||
|
||||
@@ -5,8 +5,10 @@ use crate::dealers::queries::{
|
||||
query_current_dealers_paged, query_dealer_details, query_past_dealers_paged,
|
||||
};
|
||||
use crate::dealers::transactions::try_add_dealer;
|
||||
use crate::dealings::queries::{query_dealing, query_dealing_status, query_dealings_paged};
|
||||
use crate::dealings::transactions::try_commit_dealings_chunk;
|
||||
use crate::dealings::queries::{
|
||||
query_dealing_chunk, query_dealing_chunk_status, 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,
|
||||
};
|
||||
@@ -100,8 +102,13 @@ pub fn execute(
|
||||
announce_address,
|
||||
resharing,
|
||||
),
|
||||
ExecuteMsg::CommitDealing { dealing, resharing } => {
|
||||
try_commit_dealings_chunk(deps, info, dealing, resharing)
|
||||
ExecuteMsg::CommitDealingsMetadata {
|
||||
dealing_index,
|
||||
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::CommitVerificationKeyShare { share, resharing } => {
|
||||
try_commit_verification_key_share(deps, env, info, share, resharing)
|
||||
@@ -132,6 +139,16 @@ pub fn query(deps: Deps<'_>, _env: Env, msg: QueryMsg) -> Result<QueryResponse,
|
||||
QueryMsg::GetPastDealers { limit, start_after } => {
|
||||
to_binary(&query_past_dealers_paged(deps, start_after, limit)?)?
|
||||
}
|
||||
QueryMsg::GetDealingsMetadata {
|
||||
epoch_id,
|
||||
dealer,
|
||||
dealing_index,
|
||||
} => to_binary(&query_dealing_metadata(
|
||||
deps,
|
||||
epoch_id,
|
||||
dealer,
|
||||
dealing_index,
|
||||
)?)?,
|
||||
QueryMsg::GetDealingStatus {
|
||||
epoch_id,
|
||||
dealer,
|
||||
@@ -142,22 +159,29 @@ pub fn query(deps: Deps<'_>, _env: Env, msg: QueryMsg) -> Result<QueryResponse,
|
||||
dealer,
|
||||
dealing_index,
|
||||
)?)?,
|
||||
QueryMsg::GetDealing {
|
||||
QueryMsg::GetDealingChunkStatus {
|
||||
epoch_id,
|
||||
dealer,
|
||||
dealing_index,
|
||||
} => to_binary(&query_dealing(deps, epoch_id, dealer, dealing_index)?)?,
|
||||
QueryMsg::GetDealings {
|
||||
epoch_id,
|
||||
dealer,
|
||||
limit,
|
||||
start_after,
|
||||
} => to_binary(&query_dealings_paged(
|
||||
chunk_index,
|
||||
} => to_binary(&query_dealing_chunk_status(
|
||||
deps,
|
||||
epoch_id,
|
||||
dealer,
|
||||
start_after,
|
||||
limit,
|
||||
dealing_index,
|
||||
chunk_index,
|
||||
)?)?,
|
||||
QueryMsg::GetDealingChunk {
|
||||
epoch_id,
|
||||
dealer,
|
||||
dealing_index,
|
||||
chunk_index,
|
||||
} => to_binary(&query_dealing_chunk(
|
||||
deps,
|
||||
epoch_id,
|
||||
dealer,
|
||||
dealing_index,
|
||||
chunk_index,
|
||||
)?)?,
|
||||
QueryMsg::GetVerificationKey { owner, epoch_id } => {
|
||||
to_binary(&query_vk_share(deps, owner, epoch_id)?)?
|
||||
@@ -207,8 +231,9 @@ mod tests {
|
||||
use cosmwasm_std::{coins, Addr};
|
||||
use cw4::Member;
|
||||
use cw_multi_test::{App, AppBuilder, AppResponse, ContractWrapper, Executor};
|
||||
use nym_coconut_dkg_common::dealing::DEFAULT_DEALINGS;
|
||||
use nym_coconut_dkg_common::msg::ExecuteMsg::{InitiateDkg, RegisterDealer};
|
||||
use nym_coconut_dkg_common::types::{NodeIndex, DEFAULT_DEALINGS};
|
||||
use nym_coconut_dkg_common::types::NodeIndex;
|
||||
use nym_group_contract_common::msg::InstantiateMsg as GroupInstantiateMsg;
|
||||
|
||||
fn instantiate_with_group(app: &mut App, members: &[Addr]) -> Addr {
|
||||
|
||||
@@ -1,17 +1,33 @@
|
||||
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||
// Copyright 2022-2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::dealings::storage;
|
||||
use crate::dealings::storage::StoredDealing;
|
||||
use crate::dealings::storage::{StoredDealing, DEALINGS_METADATA};
|
||||
use cosmwasm_std::{Deps, StdResult};
|
||||
use cw_storage_plus::Bound;
|
||||
use nym_coconut_dkg_common::dealer::{
|
||||
DealingResponse, DealingStatusResponse, PagedDealingsResponse,
|
||||
use nym_coconut_dkg_common::dealing::{
|
||||
DealingChunkResponse, DealingChunkStatusResponse, DealingMetadataResponse,
|
||||
DealingStatusResponse,
|
||||
};
|
||||
use nym_coconut_dkg_common::types::{DealingIndex, EpochId};
|
||||
use nym_coconut_dkg_common::types::{ChunkIndex, DealingIndex, EpochId};
|
||||
|
||||
// this does almost the same as query_dealing but doesn't return the actual dealing to make it easier on the validator
|
||||
// so it wouldn't need to deal with the deserialization
|
||||
/// Get the metadata associated with the particular dealing
|
||||
pub fn query_dealing_metadata(
|
||||
deps: Deps<'_>,
|
||||
epoch_id: EpochId,
|
||||
dealer: String,
|
||||
dealing_index: DealingIndex,
|
||||
) -> StdResult<DealingMetadataResponse> {
|
||||
let dealer = deps.api.addr_validate(&dealer)?;
|
||||
let metadata = DEALINGS_METADATA.may_load(deps.storage, (epoch_id, &dealer, dealing_index))?;
|
||||
|
||||
Ok(DealingMetadataResponse {
|
||||
epoch_id,
|
||||
dealer,
|
||||
dealing_index,
|
||||
metadata,
|
||||
})
|
||||
}
|
||||
|
||||
/// Get the status of particular dealing, i.e. whether it has been fully submitted.
|
||||
pub fn query_dealing_status(
|
||||
deps: Deps<'_>,
|
||||
epoch_id: EpochId,
|
||||
@@ -19,61 +35,70 @@ pub fn query_dealing_status(
|
||||
dealing_index: DealingIndex,
|
||||
) -> StdResult<DealingStatusResponse> {
|
||||
let dealer = deps.api.addr_validate(&dealer)?;
|
||||
let dealing_submitted = StoredDealing::exists(deps.storage, epoch_id, &dealer, dealing_index);
|
||||
let metadata = DEALINGS_METADATA.may_load(deps.storage, (epoch_id, &dealer, dealing_index))?;
|
||||
|
||||
let full_dealing_submitted = if let Some(metadata) = metadata {
|
||||
metadata.is_complete()
|
||||
} else {
|
||||
false
|
||||
};
|
||||
|
||||
Ok(DealingStatusResponse {
|
||||
epoch_id,
|
||||
dealer,
|
||||
dealing_index,
|
||||
dealing_submitted,
|
||||
full_dealing_submitted,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn query_dealing(
|
||||
/// Get the status of particular chunk, i.e. whether (and when) it has been fully submitted.
|
||||
pub fn query_dealing_chunk_status(
|
||||
deps: Deps<'_>,
|
||||
epoch_id: EpochId,
|
||||
dealer: String,
|
||||
dealing_index: DealingIndex,
|
||||
) -> StdResult<DealingResponse> {
|
||||
todo!()
|
||||
// let dealer = deps.api.addr_validate(&dealer)?;
|
||||
// let dealing = StoredDealing::read(deps.storage, epoch_id, &dealer, dealing_index);
|
||||
//
|
||||
// Ok(DealingResponse {
|
||||
// epoch_id,
|
||||
// dealer,
|
||||
// dealing_index,
|
||||
// dealing,
|
||||
// })
|
||||
chunk_index: ChunkIndex,
|
||||
) -> StdResult<DealingChunkStatusResponse> {
|
||||
let dealer = deps.api.addr_validate(&dealer)?;
|
||||
let metadata = DEALINGS_METADATA.may_load(deps.storage, (epoch_id, &dealer, dealing_index))?;
|
||||
|
||||
let submission_height = if let Some(metadata) = metadata {
|
||||
if let Some(chunk) = metadata.submitted_chunks.get(&chunk_index) {
|
||||
chunk.submission_height
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
Ok(DealingChunkStatusResponse {
|
||||
epoch_id,
|
||||
dealer,
|
||||
dealing_index,
|
||||
chunk_index,
|
||||
submission_height,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn query_dealings_paged(
|
||||
/// Get the particular chunk of the dealing.
|
||||
pub fn query_dealing_chunk(
|
||||
deps: Deps<'_>,
|
||||
epoch_id: EpochId,
|
||||
dealer: String,
|
||||
start_after: Option<DealingIndex>,
|
||||
limit: Option<u32>,
|
||||
) -> StdResult<PagedDealingsResponse> {
|
||||
todo!()
|
||||
// let limit = limit
|
||||
// .unwrap_or(storage::DEALINGS_PAGE_DEFAULT_LIMIT)
|
||||
// .min(storage::DEALINGS_PAGE_MAX_LIMIT);
|
||||
//
|
||||
// let dealer = deps.api.addr_validate(&dealer)?;
|
||||
// let start = start_after.map(Bound::exclusive);
|
||||
//
|
||||
// let dealings = StoredDealing::prefix_range(deps.storage, (epoch_id, &dealer), start)
|
||||
// .take(limit as usize)
|
||||
// .collect::<StdResult<Vec<_>>>()?;
|
||||
//
|
||||
// let start_next_after = dealings.last().map(|dealing| dealing.dealing_index);
|
||||
//
|
||||
// Ok(PagedDealingsResponse::new(
|
||||
// epoch_id,
|
||||
// dealer,
|
||||
// dealings,
|
||||
// start_next_after,
|
||||
// ))
|
||||
dealing_index: DealingIndex,
|
||||
chunk_index: ChunkIndex,
|
||||
) -> StdResult<DealingChunkResponse> {
|
||||
let dealer = deps.api.addr_validate(&dealer)?;
|
||||
let chunk = StoredDealing::read(deps.storage, epoch_id, &dealer, dealing_index, chunk_index);
|
||||
|
||||
Ok(DealingChunkResponse {
|
||||
epoch_id,
|
||||
dealer,
|
||||
dealing_index,
|
||||
chunk_index,
|
||||
chunk,
|
||||
})
|
||||
}
|
||||
|
||||
// #[cfg(test)]
|
||||
|
||||
@@ -1,21 +1,18 @@
|
||||
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||
// Copyright 2022-2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::error::ContractError;
|
||||
use cosmwasm_std::{Addr, Order, Record, StdResult, Storage};
|
||||
use cw_storage_plus::{Bound, Key, KeyDeserialize, Map, Path, Prefix, Prefixer, PrimaryKey};
|
||||
use nym_coconut_dkg_common::dealing::{DealingMetadata, PartialContractDealing};
|
||||
use nym_coconut_dkg_common::types::{
|
||||
ChunkIndex, ContractSafeBytes, DealingIndex, DealingMetadata, EpochId, PartialContractDealing,
|
||||
PartialContractDealingData,
|
||||
ChunkIndex, ContractSafeBytes, DealingIndex, EpochId, PartialContractDealingData,
|
||||
};
|
||||
|
||||
pub(crate) const DEALINGS_PAGE_MAX_LIMIT: u32 = 2;
|
||||
pub(crate) const DEALINGS_PAGE_DEFAULT_LIMIT: u32 = 1;
|
||||
|
||||
type Dealer<'a> = &'a Addr;
|
||||
|
||||
/// Metadata for a dealing for given `EpochId`, submitted by particular `Dealer` for given `DealingIndex`.
|
||||
const DEALINGS_METADATA: Map<(EpochId, Dealer, DealingIndex), DealingMetadata> =
|
||||
pub(crate) const DEALINGS_METADATA: Map<(EpochId, Dealer, DealingIndex), DealingMetadata> =
|
||||
Map::new("dealings_metadata");
|
||||
|
||||
pub(crate) fn metadata_exists(
|
||||
@@ -61,7 +58,7 @@ pub(crate) fn store_metadata(
|
||||
Ok(DEALINGS_METADATA.save(storage, (epoch_id, dealer, dealing_index), metadata)?)
|
||||
}
|
||||
|
||||
// dealings are stored in a multilevel map with the following hierarchy:
|
||||
// dealings data is stored in a multilevel map with the following hierarchy:
|
||||
// - epoch-id:
|
||||
// - issuer-address:
|
||||
// - dealing id:
|
||||
@@ -69,7 +66,6 @@ pub(crate) fn store_metadata(
|
||||
// - dealing content
|
||||
// NOTE: we're storing raw bytes bypassing serialization, so we can't use the `Map` type,
|
||||
// thus make sure you always use the below methods for using the storage!
|
||||
|
||||
pub(crate) struct StoredDealing;
|
||||
|
||||
impl StoredDealing {
|
||||
@@ -77,13 +73,12 @@ impl StoredDealing {
|
||||
|
||||
fn deserialize_dealing_record(
|
||||
kv: Record,
|
||||
) -> StdResult<(DealingIndex, PartialContractDealingData)> {
|
||||
todo!()
|
||||
// let (k, v) = kv;
|
||||
// let index = <DealingIndex as KeyDeserialize>::from_vec(k)?;
|
||||
// let data = ContractSafeBytes(v);
|
||||
//
|
||||
// Ok((index, data))
|
||||
) -> StdResult<(ChunkIndex, PartialContractDealingData)> {
|
||||
let (k, v) = kv;
|
||||
let index = <ChunkIndex as KeyDeserialize>::from_vec(k)?;
|
||||
let data = ContractSafeBytes(v);
|
||||
|
||||
Ok((index, data))
|
||||
}
|
||||
|
||||
fn storage_key(
|
||||
@@ -102,25 +97,37 @@ impl StoredDealing {
|
||||
)
|
||||
}
|
||||
|
||||
// fn prefix(prefix: (EpochId, Dealer)) -> Prefix<DealingIndex, ContractSafeBytes, DealingIndex> {
|
||||
// todo!()
|
||||
// // Prefix::with_deserialization_functions(
|
||||
// // Self::NAMESPACE,
|
||||
// // &prefix.prefix(),
|
||||
// // &[],
|
||||
// // // explicitly panic to make sure we're never attempting to call an unexpected deserializer on our data
|
||||
// // |_, _, kv| Self::deserialize_dealing_record(kv),
|
||||
// // |_, _, _| panic!("attempted to call custom de_fn_v"),
|
||||
// // )
|
||||
// }
|
||||
fn prefix(
|
||||
prefix: (EpochId, Dealer, DealingIndex),
|
||||
) -> Prefix<ChunkIndex, PartialContractDealingData, ChunkIndex> {
|
||||
Prefix::with_deserialization_functions(
|
||||
Self::NAMESPACE,
|
||||
&prefix.prefix(),
|
||||
&[],
|
||||
// explicitly panic to make sure we're never attempting to call an unexpected deserializer on our data
|
||||
|_, _, kv| Self::deserialize_dealing_record(kv),
|
||||
|_, _, _| panic!("attempted to call custom de_fn_v"),
|
||||
)
|
||||
}
|
||||
|
||||
pub(crate) fn exists(
|
||||
storage: &dyn Storage,
|
||||
epoch_id: EpochId,
|
||||
dealer: &Addr,
|
||||
dealing_index: DealingIndex,
|
||||
) -> bool {
|
||||
todo!()
|
||||
chunk_index: ChunkIndex,
|
||||
) -> StdResult<bool> {
|
||||
// whenever the dealing is saved, the metadata is appropriately updated
|
||||
// reading metadata is way cheaper than the dealing chunk itself
|
||||
let Some(metadata) =
|
||||
DEALINGS_METADATA.may_load(storage, (epoch_id, dealer, dealing_index))?
|
||||
else {
|
||||
return Ok(false);
|
||||
};
|
||||
let Some(chunk_info) = metadata.submitted_chunks.get(&chunk_index) else {
|
||||
return Ok(false);
|
||||
};
|
||||
Ok(chunk_info.submission_height.is_some())
|
||||
// StoredDealing::storage_key(epoch_id, dealer, dealing_index).has(storage)
|
||||
}
|
||||
|
||||
@@ -128,12 +135,16 @@ impl StoredDealing {
|
||||
storage: &mut dyn Storage,
|
||||
epoch_id: EpochId,
|
||||
dealer: Dealer,
|
||||
dealing: PartialContractDealing,
|
||||
dealng_chunk: PartialContractDealing,
|
||||
) {
|
||||
// NOTE: we're storing bytes directly here!
|
||||
let storage_key =
|
||||
Self::storage_key(epoch_id, dealer, dealing.dealing_index, dealing.chunk_index);
|
||||
storage.set(&storage_key, dealing.data.as_slice());
|
||||
let storage_key = Self::storage_key(
|
||||
epoch_id,
|
||||
dealer,
|
||||
dealng_chunk.dealing_index,
|
||||
dealng_chunk.chunk_index,
|
||||
);
|
||||
storage.set(&storage_key, dealng_chunk.data.as_slice());
|
||||
}
|
||||
|
||||
pub(crate) fn read(
|
||||
@@ -147,209 +158,264 @@ impl StoredDealing {
|
||||
storage.get(&storage_key).map(ContractSafeBytes)
|
||||
}
|
||||
|
||||
// pub(crate) fn prefix_range<'a>(
|
||||
// storage: &'a dyn Storage,
|
||||
// prefix: (EpochId, Dealer),
|
||||
// start: Option<Bound<DealingIndex>>,
|
||||
// ) -> impl Iterator<Item = StdResult<PartialContractDealing>> + 'a {
|
||||
// vec![].into_iter()
|
||||
// // todo!()
|
||||
// // Self::prefix(prefix)
|
||||
// // .range(storage, start, None, Order::Ascending)
|
||||
// // .map(|maybe_record| maybe_record.map(Into::into))
|
||||
// }
|
||||
pub(crate) fn prefix_range<'a>(
|
||||
storage: &'a dyn Storage,
|
||||
prefix: (EpochId, Dealer, DealingIndex),
|
||||
start: Option<Bound<ChunkIndex>>,
|
||||
) -> impl Iterator<Item = StdResult<PartialContractDealing>> + 'a {
|
||||
let dealing_index = prefix.2;
|
||||
Self::prefix(prefix)
|
||||
.range(storage, start, None, Order::Ascending)
|
||||
.map(move |maybe_record| {
|
||||
maybe_record.map(|(chunk_index, data)| PartialContractDealing {
|
||||
dealing_index,
|
||||
chunk_index,
|
||||
data,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// iterate over all values, only to be used in tests due to the amount of data being returned
|
||||
#[cfg(test)]
|
||||
#[allow(clippy::type_complexity)]
|
||||
pub(crate) fn unchecked_all_entries(
|
||||
storage: &dyn Storage,
|
||||
) -> Vec<((EpochId, Addr, DealingIndex), PartialContractDealingData)> {
|
||||
todo!()
|
||||
// type StorageKey<'a> = (EpochId, Dealer<'a>, DealingIndex);
|
||||
//
|
||||
// let empty_prefix: Prefix<StorageKey, ContractDealing, StorageKey> =
|
||||
// Prefix::with_deserialization_functions(
|
||||
// Self::NAMESPACE,
|
||||
// &[],
|
||||
// &[],
|
||||
// |_, _, kv| StorageKey::from_vec(kv.0).map(|kt| (kt, ContractSafeBytes(kv.1))),
|
||||
// |_, _, _| unimplemented!(),
|
||||
// );
|
||||
//
|
||||
// empty_prefix
|
||||
// .range(storage, None, None, Order::Ascending)
|
||||
// .collect::<StdResult<_>>()
|
||||
// .unwrap()
|
||||
) -> Vec<(
|
||||
(EpochId, Addr, (DealingIndex, ChunkIndex)),
|
||||
PartialContractDealingData,
|
||||
)> {
|
||||
type StorageKey<'a> = (EpochId, Dealer<'a>, (DealingIndex, ChunkIndex));
|
||||
|
||||
let empty_prefix: Prefix<StorageKey, PartialContractDealingData, StorageKey> =
|
||||
Prefix::with_deserialization_functions(
|
||||
Self::NAMESPACE,
|
||||
&[],
|
||||
&[],
|
||||
|_, _, kv| StorageKey::from_vec(kv.0).map(|kt| (kt, ContractSafeBytes(kv.1))),
|
||||
|_, _, _| unimplemented!(),
|
||||
);
|
||||
|
||||
empty_prefix
|
||||
.range(storage, None, None, Order::Ascending)
|
||||
.collect::<StdResult<_>>()
|
||||
.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
// #[cfg(test)]
|
||||
// mod tests {
|
||||
// use super::*;
|
||||
// use crate::support::tests::helpers::init_contract;
|
||||
// use std::collections::HashMap;
|
||||
//
|
||||
// fn dealing_data(
|
||||
// epoch_id: EpochId,
|
||||
// dealer: Dealer,
|
||||
// dealing_index: DealingIndex,
|
||||
// ) -> PartialContractDealingData {
|
||||
// ContractSafeBytes(
|
||||
// format!("{epoch_id},{dealer},{dealing_index}")
|
||||
// .as_bytes()
|
||||
// .to_vec(),
|
||||
// )
|
||||
// }
|
||||
//
|
||||
// #[test]
|
||||
// fn saving_dealing() {
|
||||
// let mut deps = init_contract();
|
||||
//
|
||||
// // make sure to check all combinations of epoch id, dealer address and dealing index to ensure nothing overlaps
|
||||
// let epochs = [54, 423, 754];
|
||||
// let dealers = [
|
||||
// Addr::unchecked("dealer1"),
|
||||
// Addr::unchecked("dealer2"),
|
||||
// Addr::unchecked("dealer3"),
|
||||
// Addr::unchecked("dealer4"),
|
||||
// Addr::unchecked("dealer5"),
|
||||
// ];
|
||||
// let dealing_indices = [0, 1, 2, 3, 4, 5, 6, 7];
|
||||
//
|
||||
// for epoch_id in &epochs {
|
||||
// for dealer in &dealers {
|
||||
// for dealing_index in &dealing_indices {
|
||||
// assert!(!StoredDealing::exists(
|
||||
// &deps.storage,
|
||||
// *epoch_id,
|
||||
// dealer,
|
||||
// *dealing_index
|
||||
// ));
|
||||
//
|
||||
// StoredDealing::save(
|
||||
// deps.as_mut().storage,
|
||||
// *epoch_id,
|
||||
// dealer,
|
||||
// PartialContractDealing {
|
||||
// dealing_index: *dealing_index,
|
||||
// data: dealing_data(*epoch_id, dealer, *dealing_index),
|
||||
// },
|
||||
// )
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// let all: HashMap<_, _> = StoredDealing::unchecked_all_entries(&deps.storage)
|
||||
// .into_iter()
|
||||
// .collect();
|
||||
// assert_eq!(
|
||||
// all.len(),
|
||||
// epochs.len() * dealers.len() * dealing_indices.len()
|
||||
// );
|
||||
//
|
||||
// for epoch_id in &epochs {
|
||||
// for dealer in &dealers {
|
||||
// for dealing_index in &dealing_indices {
|
||||
// assert!(StoredDealing::exists(
|
||||
// &deps.storage,
|
||||
// *epoch_id,
|
||||
// dealer,
|
||||
// *dealing_index
|
||||
// ));
|
||||
//
|
||||
// let content =
|
||||
// StoredDealing::read(&deps.storage, *epoch_id, dealer, *dealing_index)
|
||||
// .unwrap();
|
||||
// let expected = dealing_data(*epoch_id, dealer, *dealing_index);
|
||||
// assert_eq!(expected, content);
|
||||
// assert_eq!(
|
||||
// &expected,
|
||||
// all.get(&(*epoch_id, dealer.clone(), *dealing_index))
|
||||
// .unwrap()
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// #[test]
|
||||
// fn iterating_over_dealings() {
|
||||
// let mut deps = init_contract();
|
||||
//
|
||||
// let epochs = [54, 423, 754];
|
||||
// let dealers = [
|
||||
// Addr::unchecked("dealer1"),
|
||||
// Addr::unchecked("dealer2"),
|
||||
// Addr::unchecked("dealer3"),
|
||||
// Addr::unchecked("dealer4"),
|
||||
// Addr::unchecked("dealer5"),
|
||||
// ];
|
||||
// let dealing_indices = [0, 1, 2, 3, 4, 5, 6, 7];
|
||||
//
|
||||
// for epoch_id in &epochs {
|
||||
// for dealer in &dealers {
|
||||
// for dealing_index in &dealing_indices {
|
||||
// StoredDealing::save(
|
||||
// deps.as_mut().storage,
|
||||
// *epoch_id,
|
||||
// dealer,
|
||||
// PartialContractDealing {
|
||||
// dealing_index: *dealing_index,
|
||||
// data: dealing_data(*epoch_id, dealer, *dealing_index),
|
||||
// },
|
||||
// )
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // remember, we're not testing the iterator implementation
|
||||
//
|
||||
// // nothing under epoch 0
|
||||
// let dealings =
|
||||
// StoredDealing::prefix_range(&deps.storage, (0, &dealers[0]), None).collect::<Vec<_>>();
|
||||
// assert!(dealings.is_empty());
|
||||
//
|
||||
// // nothing for dealer "foo"
|
||||
// let foo = Addr::unchecked("foo");
|
||||
// let dealings =
|
||||
// StoredDealing::prefix_range(&deps.storage, (epochs[0], &foo), None).collect::<Vec<_>>();
|
||||
// assert!(dealings.is_empty());
|
||||
//
|
||||
// let all = StoredDealing::prefix_range(&deps.storage, (epochs[0], &dealers[0]), None)
|
||||
// .collect::<Vec<_>>();
|
||||
// assert_eq!(all.len(), dealing_indices.len());
|
||||
//
|
||||
// for (i, dealing) in all.iter().enumerate() {
|
||||
// let expected = dealing_data(epochs[0], &dealers[0], dealing_indices[i]);
|
||||
// assert_eq!(expected, dealing.as_ref().unwrap().data);
|
||||
// assert_eq!(dealing_indices[i], dealing.as_ref().unwrap().dealing_index);
|
||||
// }
|
||||
//
|
||||
// // for sanity sake, check another dealer with different epoch
|
||||
// let all_other = StoredDealing::prefix_range(&deps.storage, (epochs[2], &dealers[3]), None)
|
||||
// .collect::<Vec<_>>();
|
||||
// assert_eq!(all_other.len(), dealing_indices.len());
|
||||
//
|
||||
// for (i, dealing) in all_other.iter().enumerate() {
|
||||
// let expected = dealing_data(epochs[2], &dealers[3], dealing_indices[i]);
|
||||
// assert_eq!(expected, dealing.as_ref().unwrap().data);
|
||||
// assert_eq!(dealing_indices[i], dealing.as_ref().unwrap().dealing_index);
|
||||
// }
|
||||
//
|
||||
// let without_first = StoredDealing::prefix_range(
|
||||
// &deps.storage,
|
||||
// (epochs[0], &dealers[0]),
|
||||
// Some(Bound::exclusive(dealing_indices[0])),
|
||||
// )
|
||||
// .collect::<Vec<_>>();
|
||||
// assert_eq!(&all[1..], without_first);
|
||||
//
|
||||
// let mid = StoredDealing::prefix_range(
|
||||
// &deps.storage,
|
||||
// (epochs[0], &dealers[0]),
|
||||
// Some(Bound::inclusive(dealing_indices[3])),
|
||||
// )
|
||||
// .collect::<Vec<_>>();
|
||||
// assert_eq!(&all[3..], mid);
|
||||
// }
|
||||
// }
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::support::tests::helpers::init_contract;
|
||||
use std::collections::HashMap;
|
||||
|
||||
fn dealing_data(
|
||||
epoch_id: EpochId,
|
||||
dealer: Dealer,
|
||||
dealing_index: DealingIndex,
|
||||
chunk_index: ChunkIndex,
|
||||
) -> PartialContractDealingData {
|
||||
ContractSafeBytes(
|
||||
format!("{epoch_id},{dealer},{dealing_index},{chunk_index}")
|
||||
.as_bytes()
|
||||
.to_vec(),
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn saving_dealing_chunks() {
|
||||
let mut deps = init_contract();
|
||||
|
||||
fn exists_in_storage(
|
||||
storage: &dyn Storage,
|
||||
epoch_id: EpochId,
|
||||
dealer: Dealer,
|
||||
dealing_index: DealingIndex,
|
||||
chunk_index: ChunkIndex,
|
||||
) -> bool {
|
||||
StoredDealing::storage_key(epoch_id, dealer, dealing_index, chunk_index).has(storage)
|
||||
}
|
||||
|
||||
// make sure to check all combinations of epoch id, dealer address and dealing index to ensure nothing overlaps
|
||||
let epochs = [54, 423, 754];
|
||||
let dealers = [
|
||||
Addr::unchecked("dealer1"),
|
||||
Addr::unchecked("dealer2"),
|
||||
Addr::unchecked("dealer3"),
|
||||
Addr::unchecked("dealer4"),
|
||||
Addr::unchecked("dealer5"),
|
||||
];
|
||||
let dealing_indices = [0, 1, 2, 3, 4, 5, 6, 7];
|
||||
let chunk_indices = [0, 1, 2, 3, 4];
|
||||
|
||||
for epoch_id in &epochs {
|
||||
for dealer in &dealers {
|
||||
for dealing_index in &dealing_indices {
|
||||
for chunk_index in &chunk_indices {
|
||||
assert!(!exists_in_storage(
|
||||
&deps.storage,
|
||||
*epoch_id,
|
||||
dealer,
|
||||
*dealing_index,
|
||||
*chunk_index
|
||||
));
|
||||
|
||||
StoredDealing::save(
|
||||
deps.as_mut().storage,
|
||||
*epoch_id,
|
||||
dealer,
|
||||
PartialContractDealing {
|
||||
dealing_index: *dealing_index,
|
||||
chunk_index: *chunk_index,
|
||||
data: dealing_data(*epoch_id, dealer, *dealing_index, *chunk_index),
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let all: HashMap<_, _> = StoredDealing::unchecked_all_entries(&deps.storage)
|
||||
.into_iter()
|
||||
.collect();
|
||||
assert_eq!(
|
||||
all.len(),
|
||||
epochs.len() * dealers.len() * dealing_indices.len() * chunk_indices.len()
|
||||
);
|
||||
|
||||
for epoch_id in &epochs {
|
||||
for dealer in &dealers {
|
||||
for dealing_index in &dealing_indices {
|
||||
for chunk_index in &chunk_indices {
|
||||
assert!(exists_in_storage(
|
||||
&deps.storage,
|
||||
*epoch_id,
|
||||
dealer,
|
||||
*dealing_index,
|
||||
*chunk_index
|
||||
));
|
||||
|
||||
let content = StoredDealing::read(
|
||||
&deps.storage,
|
||||
*epoch_id,
|
||||
dealer,
|
||||
*dealing_index,
|
||||
*chunk_index,
|
||||
)
|
||||
.unwrap();
|
||||
let expected =
|
||||
dealing_data(*epoch_id, dealer, *dealing_index, *chunk_index);
|
||||
assert_eq!(expected, content);
|
||||
assert_eq!(
|
||||
&expected,
|
||||
all.get(&(*epoch_id, dealer.clone(), (*dealing_index, *chunk_index)))
|
||||
.unwrap()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn iterating_over_dealing_chunks() {
|
||||
let mut deps = init_contract();
|
||||
|
||||
let epochs = [54, 423, 754];
|
||||
let dealers = [
|
||||
Addr::unchecked("dealer1"),
|
||||
Addr::unchecked("dealer2"),
|
||||
Addr::unchecked("dealer3"),
|
||||
Addr::unchecked("dealer4"),
|
||||
Addr::unchecked("dealer5"),
|
||||
];
|
||||
let dealing_indices = [0, 1, 2, 3, 4, 5, 6, 7];
|
||||
let chunk_indices = [0, 1, 2, 3, 4];
|
||||
|
||||
for epoch_id in &epochs {
|
||||
for dealer in &dealers {
|
||||
for dealing_index in &dealing_indices {
|
||||
for chunk_index in &chunk_indices {
|
||||
StoredDealing::save(
|
||||
deps.as_mut().storage,
|
||||
*epoch_id,
|
||||
dealer,
|
||||
PartialContractDealing {
|
||||
dealing_index: *dealing_index,
|
||||
chunk_index: *chunk_index,
|
||||
data: dealing_data(*epoch_id, dealer, *dealing_index, *chunk_index),
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// remember, we're not testing the iterator implementation
|
||||
|
||||
// nothing under epoch 0
|
||||
let dealings =
|
||||
StoredDealing::prefix_range(&deps.storage, (0, &dealers[0], dealing_indices[0]), None)
|
||||
.collect::<Vec<_>>();
|
||||
assert!(dealings.is_empty());
|
||||
|
||||
// nothing for dealer "foo"
|
||||
let foo = Addr::unchecked("foo");
|
||||
let dealings =
|
||||
StoredDealing::prefix_range(&deps.storage, (epochs[0], &foo, dealing_indices[0]), None)
|
||||
.collect::<Vec<_>>();
|
||||
assert!(dealings.is_empty());
|
||||
|
||||
// nothing for dealing index 99
|
||||
let dealings =
|
||||
StoredDealing::prefix_range(&deps.storage, (epochs[0], &dealers[0], 99), None)
|
||||
.collect::<Vec<_>>();
|
||||
assert!(dealings.is_empty());
|
||||
|
||||
let all = StoredDealing::prefix_range(
|
||||
&deps.storage,
|
||||
(epochs[0], &dealers[0], dealing_indices[0]),
|
||||
None,
|
||||
)
|
||||
.collect::<Vec<_>>();
|
||||
assert_eq!(all.len(), chunk_indices.len());
|
||||
|
||||
for (i, dealing) in all.iter().enumerate() {
|
||||
let expected =
|
||||
dealing_data(epochs[0], &dealers[0], dealing_indices[0], chunk_indices[i]);
|
||||
assert_eq!(expected, dealing.as_ref().unwrap().data);
|
||||
assert_eq!(chunk_indices[i], dealing.as_ref().unwrap().chunk_index);
|
||||
}
|
||||
|
||||
// for sanity sake, check another dealer with different epoch and different dealing index
|
||||
let all_other = StoredDealing::prefix_range(
|
||||
&deps.storage,
|
||||
(epochs[2], &dealers[3], dealing_indices[4]),
|
||||
None,
|
||||
)
|
||||
.collect::<Vec<_>>();
|
||||
assert_eq!(all_other.len(), chunk_indices.len());
|
||||
|
||||
for (i, dealing) in all_other.iter().enumerate() {
|
||||
let expected =
|
||||
dealing_data(epochs[2], &dealers[3], dealing_indices[4], chunk_indices[i]);
|
||||
assert_eq!(expected, dealing.as_ref().unwrap().data);
|
||||
assert_eq!(chunk_indices[i], dealing.as_ref().unwrap().chunk_index);
|
||||
}
|
||||
|
||||
let without_first = StoredDealing::prefix_range(
|
||||
&deps.storage,
|
||||
(epochs[0], &dealers[0], dealing_indices[0]),
|
||||
Some(Bound::exclusive(chunk_indices[0])),
|
||||
)
|
||||
.collect::<Vec<_>>();
|
||||
assert_eq!(&all[1..], without_first);
|
||||
|
||||
let mid = StoredDealing::prefix_range(
|
||||
&deps.storage,
|
||||
(epochs[0], &dealers[0], dealing_indices[0]),
|
||||
Some(Bound::inclusive(chunk_indices[3])),
|
||||
)
|
||||
.collect::<Vec<_>>();
|
||||
assert_eq!(&all[3..], mid);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||
// Copyright 2022-2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::dealers::storage as dealers_storage;
|
||||
@@ -10,9 +10,10 @@ use crate::epoch_state::utils::check_epoch_state;
|
||||
use crate::error::ContractError;
|
||||
use crate::state::storage::STATE;
|
||||
use cosmwasm_std::{Addr, DepsMut, Env, MessageInfo, Response, Storage};
|
||||
use nym_coconut_dkg_common::types::{
|
||||
DealingMetadata, EpochState, PartialContractDealing, MAX_DEALING_CHUNKS,
|
||||
use nym_coconut_dkg_common::dealing::{
|
||||
DealingChunkInfo, DealingMetadata, PartialContractDealing, MAX_DEALING_CHUNKS,
|
||||
};
|
||||
use nym_coconut_dkg_common::types::{ChunkIndex, DealingIndex, EpochState};
|
||||
|
||||
// make sure the epoch is in the dealing exchange and the message sender is a valid dealer for this epoch
|
||||
fn ensure_permission(
|
||||
@@ -43,7 +44,8 @@ fn ensure_permission(
|
||||
pub fn try_submit_dealings_metadata(
|
||||
deps: DepsMut,
|
||||
info: MessageInfo,
|
||||
metadata: DealingMetadata,
|
||||
dealing_index: DealingIndex,
|
||||
chunks: Vec<DealingChunkInfo>,
|
||||
resharing: bool,
|
||||
) -> Result<Response, ContractError> {
|
||||
ensure_permission(deps.storage, &info.sender, resharing)?;
|
||||
@@ -52,85 +54,80 @@ pub fn try_submit_dealings_metadata(
|
||||
let epoch = CURRENT_EPOCH.load(deps.storage)?;
|
||||
|
||||
// don't allow overwriting existing metadata
|
||||
if metadata_exists(
|
||||
deps.storage,
|
||||
epoch.epoch_id,
|
||||
&info.sender,
|
||||
metadata.dealing_index,
|
||||
) {
|
||||
if metadata_exists(deps.storage, epoch.epoch_id, &info.sender, dealing_index) {
|
||||
return Err(ContractError::MetadataAlreadyExists {
|
||||
epoch_id: epoch.epoch_id,
|
||||
dealer: info.sender,
|
||||
dealing_index: metadata.dealing_index,
|
||||
});
|
||||
}
|
||||
|
||||
// make sure the metadata is not empty
|
||||
if metadata.submitted_chunks.is_empty() {
|
||||
return Err(ContractError::EmptyMetadata {
|
||||
epoch_id: epoch.epoch_id,
|
||||
dealer: info.sender,
|
||||
dealing_index: metadata.dealing_index,
|
||||
});
|
||||
}
|
||||
|
||||
// make sure the dealing has non-zero size
|
||||
if metadata.total_size() == 0 {
|
||||
return Err(ContractError::EmptyMetadata {
|
||||
epoch_id: epoch.epoch_id,
|
||||
dealer: info.sender,
|
||||
dealing_index: metadata.dealing_index,
|
||||
dealing_index,
|
||||
});
|
||||
}
|
||||
|
||||
// make sure the dealing index is in the allowed range
|
||||
// note: dealing indexing starts from 0
|
||||
if metadata.dealing_index >= state.key_size {
|
||||
if dealing_index >= state.key_size {
|
||||
return Err(ContractError::DealingOutOfRange {
|
||||
epoch_id: epoch.epoch_id,
|
||||
dealer: info.sender,
|
||||
index: metadata.dealing_index,
|
||||
index: dealing_index,
|
||||
key_size: state.key_size,
|
||||
});
|
||||
}
|
||||
|
||||
let chunks = metadata.submitted_chunks.len();
|
||||
// make sure the metadata is not empty
|
||||
if chunks.is_empty() {
|
||||
return Err(ContractError::EmptyMetadata {
|
||||
epoch_id: epoch.epoch_id,
|
||||
dealer: info.sender,
|
||||
dealing_index,
|
||||
});
|
||||
}
|
||||
|
||||
// make sure the chunks are non empty
|
||||
if chunks.iter().any(|c| c.size == 0) {
|
||||
return Err(ContractError::EmptyMetadata {
|
||||
epoch_id: epoch.epoch_id,
|
||||
dealer: info.sender,
|
||||
dealing_index,
|
||||
});
|
||||
}
|
||||
|
||||
// make sure the number of dealing chunks is in the allowed range
|
||||
// to prevent somebody splitting their dealings into 10B chunks
|
||||
if chunks > MAX_DEALING_CHUNKS {
|
||||
if chunks.len() > MAX_DEALING_CHUNKS {
|
||||
return Err(ContractError::TooFragmentedMetadata {
|
||||
epoch_id: epoch.epoch_id,
|
||||
dealer: info.sender,
|
||||
dealing_index: metadata.dealing_index,
|
||||
chunks,
|
||||
dealing_index,
|
||||
chunks: chunks.len(),
|
||||
});
|
||||
}
|
||||
|
||||
// make sure all chunks, but the last one, have the same size
|
||||
// SAFETY: we checked for whether `metadata.submitted_chunks` is empty and returned an error in that case
|
||||
// SAFETY: we checked for whether `chunks` is empty and returned an error in that case
|
||||
#[allow(clippy::unwrap_used)]
|
||||
let first_chunk_size = metadata.submitted_chunks.first_key_value().unwrap().1.size;
|
||||
let first_chunk_size = chunks.first().unwrap().size;
|
||||
|
||||
for (&chunk_index, chunk_info) in metadata.submitted_chunks.iter().take(chunks - 1) {
|
||||
for (chunk_index, chunk_info) in chunks.iter().enumerate().take(chunks.len() - 1) {
|
||||
if chunk_info.size != first_chunk_size {
|
||||
return Err(ContractError::UnevenChunkSplit {
|
||||
epoch_id: epoch.epoch_id,
|
||||
dealer: info.sender,
|
||||
dealing_index: metadata.dealing_index,
|
||||
chunk_index,
|
||||
dealing_index,
|
||||
chunk_index: chunk_index as ChunkIndex,
|
||||
first_chunk_size,
|
||||
size: chunk_info.size,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// finally, store the metadata
|
||||
// finally, construct and store the metadata
|
||||
let metadata = DealingMetadata::new(dealing_index, chunks);
|
||||
|
||||
store_metadata(
|
||||
deps.storage,
|
||||
epoch.epoch_id,
|
||||
&info.sender,
|
||||
metadata.dealing_index,
|
||||
dealing_index,
|
||||
&metadata,
|
||||
)?;
|
||||
|
||||
@@ -141,7 +138,7 @@ pub fn try_commit_dealings_chunk(
|
||||
deps: DepsMut<'_>,
|
||||
env: Env,
|
||||
info: MessageInfo,
|
||||
dealing: PartialContractDealing,
|
||||
chunk: PartialContractDealing,
|
||||
resharing: bool,
|
||||
) -> Result<Response, ContractError> {
|
||||
ensure_permission(deps.storage, &info.sender, resharing)?;
|
||||
@@ -153,16 +150,16 @@ pub fn try_commit_dealings_chunk(
|
||||
deps.storage,
|
||||
epoch.epoch_id,
|
||||
&info.sender,
|
||||
dealing.dealing_index,
|
||||
chunk.dealing_index,
|
||||
)?;
|
||||
|
||||
// check if the received chunk is within the declared range
|
||||
let Some(submission_status) = metadata.submitted_chunks.get_mut(&dealing.chunk_index) else {
|
||||
let Some(submission_status) = metadata.submitted_chunks.get_mut(&chunk.chunk_index) else {
|
||||
return Err(ContractError::DealingChunkNotInMetadata {
|
||||
epoch_id: epoch.epoch_id,
|
||||
dealer: info.sender,
|
||||
dealing_index: dealing.dealing_index,
|
||||
chunk_index: dealing.chunk_index,
|
||||
dealing_index: chunk.dealing_index,
|
||||
chunk_index: chunk.chunk_index,
|
||||
});
|
||||
};
|
||||
|
||||
@@ -171,8 +168,8 @@ pub fn try_commit_dealings_chunk(
|
||||
return Err(ContractError::DealingChunkAlreadyCommitted {
|
||||
epoch_id: epoch.epoch_id,
|
||||
dealer: info.sender,
|
||||
dealing_index: dealing.dealing_index,
|
||||
chunk_index: dealing.chunk_index,
|
||||
dealing_index: chunk.dealing_index,
|
||||
chunk_index: chunk.chunk_index,
|
||||
block_height: submission_height,
|
||||
});
|
||||
}
|
||||
@@ -183,12 +180,12 @@ pub fn try_commit_dealings_chunk(
|
||||
deps.storage,
|
||||
epoch.epoch_id,
|
||||
&info.sender,
|
||||
dealing.dealing_index,
|
||||
chunk.dealing_index,
|
||||
&metadata,
|
||||
)?;
|
||||
|
||||
// store the dealing
|
||||
StoredDealing::save(deps.storage, epoch.epoch_id, &info.sender, dealing);
|
||||
StoredDealing::save(deps.storage, epoch.epoch_id, &info.sender, chunk);
|
||||
|
||||
Ok(Response::new())
|
||||
}
|
||||
@@ -205,7 +202,7 @@ pub(crate) mod tests {
|
||||
use cosmwasm_std::Addr;
|
||||
use nym_coconut_dkg_common::dealer::DealerDetails;
|
||||
use nym_coconut_dkg_common::types::{
|
||||
ContractSafeBytes, InitialReplacementData, TimeConfiguration, DEFAULT_DEALINGS,
|
||||
ContractSafeBytes, InitialReplacementData, TimeConfiguration,
|
||||
};
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
|
||||
use cosmwasm_std::{Addr, StdError};
|
||||
use cw_controllers::AdminError;
|
||||
use nym_coconut_dkg_common::types::{ChunkIndex, DealingIndex, EpochId, MAX_DEALING_CHUNKS};
|
||||
use nym_coconut_dkg_common::dealing::MAX_DEALING_CHUNKS;
|
||||
use nym_coconut_dkg_common::types::{ChunkIndex, DealingIndex, EpochId};
|
||||
use thiserror::Error;
|
||||
|
||||
/// Custom errors for contract failure conditions.
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||
// Copyright 2022-2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use cosmwasm_std::Addr;
|
||||
use nym_coconut_dkg_common::dealer::DealerDetails;
|
||||
use nym_coconut_dkg_common::types::{ContractSafeBytes, PartialContractDealing};
|
||||
use nym_coconut_dkg_common::dealing::PartialContractDealing;
|
||||
use nym_coconut_dkg_common::types::ContractSafeBytes;
|
||||
use nym_coconut_dkg_common::verification_key::ContractVKShare;
|
||||
|
||||
pub const TEST_MIX_DENOM: &str = "unym";
|
||||
@@ -24,11 +25,11 @@ pub fn dealing_bytes_fixture() -> ContractSafeBytes {
|
||||
}
|
||||
|
||||
pub fn partial_dealing_fixture() -> PartialContractDealing {
|
||||
todo!()
|
||||
// PartialContractDealing {
|
||||
// dealing_index: 0,
|
||||
// data: ContractSafeBytes(vec![1, 2, 3]),
|
||||
// }
|
||||
PartialContractDealing {
|
||||
chunk_index: 0,
|
||||
dealing_index: 0,
|
||||
data: ContractSafeBytes(vec![1, 2, 3]),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn dealer_details_fixture(assigned_index: u64) -> DealerDetails {
|
||||
|
||||
@@ -9,8 +9,9 @@ use cosmwasm_std::{
|
||||
QuerierResult, SystemResult, WasmQuery,
|
||||
};
|
||||
use cw4::{Cw4QueryMsg, Member, MemberListResponse, MemberResponse};
|
||||
use nym_coconut_dkg_common::dealing::DEFAULT_DEALINGS;
|
||||
use nym_coconut_dkg_common::msg::InstantiateMsg;
|
||||
use nym_coconut_dkg_common::types::{DealerDetails, DEFAULT_DEALINGS};
|
||||
use nym_coconut_dkg_common::types::DealerDetails;
|
||||
use std::sync::Mutex;
|
||||
|
||||
use super::fixtures::TEST_MIX_DENOM;
|
||||
|
||||
@@ -8,7 +8,7 @@ use crate::epoch_state::utils::check_epoch_state;
|
||||
use crate::error::ContractError;
|
||||
use crate::state::storage::{MULTISIG, STATE};
|
||||
use crate::verification_key_shares::storage::vk_shares;
|
||||
use cosmwasm_std::{Addr, DepsMut, Env, MessageInfo, Response};
|
||||
use cosmwasm_std::{DepsMut, Env, MessageInfo, Response};
|
||||
use nym_coconut_dkg_common::types::EpochState;
|
||||
use nym_coconut_dkg_common::verification_key::{
|
||||
to_cosmos_msg, ContractVKShare, VerificationKeyShare,
|
||||
@@ -66,9 +66,11 @@ pub fn try_commit_verification_key_share(
|
||||
pub fn try_verify_verification_key_share(
|
||||
deps: DepsMut<'_>,
|
||||
info: MessageInfo,
|
||||
owner: Addr,
|
||||
owner: String,
|
||||
resharing: bool,
|
||||
) -> Result<Response, ContractError> {
|
||||
let owner = deps.api.addr_validate(&owner)?;
|
||||
|
||||
check_epoch_state(
|
||||
deps.storage,
|
||||
EpochState::VerificationKeyFinalization { resharing },
|
||||
@@ -96,6 +98,7 @@ mod tests {
|
||||
use crate::support::tests::helpers;
|
||||
use crate::support::tests::helpers::{add_fixture_dealer, ADMIN_ADDRESS, MULTISIG_CONTRACT};
|
||||
use cosmwasm_std::testing::{mock_env, mock_info};
|
||||
use cosmwasm_std::Addr;
|
||||
use cw_controllers::AdminError;
|
||||
use nym_coconut_dkg_common::dealer::DealerDetails;
|
||||
use nym_coconut_dkg_common::types::{EpochState, TimeConfiguration};
|
||||
@@ -233,7 +236,7 @@ mod tests {
|
||||
try_initiate_dkg(deps.as_mut(), env.clone(), mock_info(ADMIN_ADDRESS, &[])).unwrap();
|
||||
|
||||
let info = mock_info("requester", &[]);
|
||||
let owner = Addr::unchecked("owner");
|
||||
let owner = "owner".to_string();
|
||||
let multisig_info = mock_info(MULTISIG_CONTRACT, &[]);
|
||||
|
||||
let ret =
|
||||
@@ -291,7 +294,7 @@ mod tests {
|
||||
let mut env = mock_env();
|
||||
try_initiate_dkg(deps.as_mut(), env.clone(), mock_info(ADMIN_ADDRESS, &[])).unwrap();
|
||||
|
||||
let owner = Addr::unchecked("owner");
|
||||
let owner = "owner".to_string();
|
||||
let info = mock_info(owner.as_ref(), &[]);
|
||||
let share = "share".to_string();
|
||||
let multisig_info = mock_info(MULTISIG_CONTRACT, &[]);
|
||||
@@ -309,14 +312,18 @@ mod tests {
|
||||
advance_epoch_state(deps.as_mut(), env.clone()).unwrap();
|
||||
|
||||
let dealer_details = DealerDetails {
|
||||
address: owner.clone(),
|
||||
address: Addr::unchecked(&owner),
|
||||
bte_public_key_with_proof: String::new(),
|
||||
ed25519_identity: String::new(),
|
||||
announce_address: String::new(),
|
||||
assigned_index: 1,
|
||||
};
|
||||
dealers_storage::current_dealers()
|
||||
.save(deps.as_mut().storage, &owner, &dealer_details)
|
||||
.save(
|
||||
deps.as_mut().storage,
|
||||
&Addr::unchecked(&owner),
|
||||
&dealer_details,
|
||||
)
|
||||
.unwrap();
|
||||
try_commit_verification_key_share(deps.as_mut(), env.clone(), info, share, false).unwrap();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user