Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/migrate hidden delegations #786

Merged
merged 26 commits into from
Sep 30, 2021
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
b205f4f
Remove migration code
neacsu Sep 21, 2021
45a1428
Added function to iterate over delegation of variable type
neacsu Sep 21, 2021
c9e5156
Add unit tests
neacsu Sep 21, 2021
c988804
Refactored some naming and reused mix/gateway functionality
neacsu Sep 21, 2021
839d82b
Borrow bucket instead of move
neacsu Sep 22, 2021
ceee872
Linked with existing delegations function
neacsu Sep 22, 2021
8272a52
Migration of left-over delegations
neacsu Sep 22, 2021
6c5f30b
Remove unused imports
neacsu Sep 22, 2021
ddfde91
Put a gateway test as well, next to the mix one
neacsu Sep 22, 2021
2bff53c
Expose queries for all delegations
neacsu Sep 22, 2021
6f6bd69
Change break point
neacsu Sep 22, 2021
252c44b
Added client side calls to the new queries
neacsu Sep 22, 2021
3cae621
Fix clippy
neacsu Sep 23, 2021
52f4c76
Added pagination and read check tests
neacsu Sep 23, 2021
38be535
Fix gateway test from the last commit
neacsu Sep 23, 2021
176dea3
Test functions for (de)serialization of identity and owner (in)to sto…
neacsu Sep 23, 2021
c7d6933
Add delegation function unit test
neacsu Sep 23, 2021
c27df51
Feature guard import
neacsu Sep 23, 2021
44bc14c
Changed UnpackedDelegation from type to struct
neacsu Sep 27, 2021
9aa66e9
Remove mutable parameter and put start_after in returned value
neacsu Sep 27, 2021
639cb58
Made all delegations into iterator for OOM safety
neacsu Sep 27, 2021
b5001eb
Fix clippy
neacsu Sep 27, 2021
ac2826d
Merge remote-tracking branch 'origin/develop' into feature/migrate_hi…
neacsu Sep 28, 2021
17fa3bc
Add test for delegations iterator size in memory
neacsu Sep 28, 2021
f2c5e1e
Change map with if let for ease of read
neacsu Sep 29, 2021
6b3ce37
Use DENOM instead of hardcoded value
neacsu Sep 29, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 59 additions & 3 deletions common/client-libs/validator-client/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::nymd::{
};
use crate::{validator_api, ValidatorClientError};
use coconut_interface::{BlindSignRequestBody, BlindedSignatureResponse, VerificationKeyResponse};
use mixnet_contract::{GatewayBond, MixNodeBond};
use mixnet_contract::{GatewayBond, MixNodeBond, RawDelegationData};
neacsu marked this conversation as resolved.
Show resolved Hide resolved
use url::Url;

#[cfg(feature = "nymd-client")]
Expand Down Expand Up @@ -213,7 +213,7 @@ impl<C> Client<C> {
Ok(gateways)
}

pub async fn get_all_nymd_mixnode_delegations(
pub async fn get_all_nymd_single_mixnode_delegations(
&self,
identity: mixnet_contract::IdentityKey,
) -> Result<Vec<mixnet_contract::Delegation>, ValidatorClientError>
Expand Down Expand Up @@ -243,6 +243,34 @@ impl<C> Client<C> {
Ok(delegations)
}

pub async fn get_all_nymd_mixnode_delegations(
&self,
) -> Result<Vec<mixnet_contract::UnpackedDelegation<RawDelegationData>>, ValidatorClientError>
where
C: CosmWasmClient + Sync,
{
let mut delegations = Vec::new();
let mut start_after = None;
loop {
let mut paged_response = self
.nymd
.get_all_mix_delegations_paged(
start_after.take(),
self.mixnode_delegations_page_limit,
)
.await?;
delegations.append(&mut paged_response.delegations);

if let Some(start_after_res) = paged_response.start_next_after {
start_after = Some(start_after_res)
} else {
break;
}
}

Ok(delegations)
}

pub async fn get_all_nymd_reverse_mixnode_delegations(
&self,
delegation_owner: &cosmrs::AccountId,
Expand Down Expand Up @@ -295,7 +323,7 @@ impl<C> Client<C> {
Ok(delegations)
}

pub async fn get_all_nymd_gateway_delegations(
pub async fn get_all_nymd_single_gateway_delegations(
&self,
identity: mixnet_contract::IdentityKey,
) -> Result<Vec<mixnet_contract::Delegation>, ValidatorClientError>
Expand Down Expand Up @@ -325,6 +353,34 @@ impl<C> Client<C> {
Ok(delegations)
}

pub async fn get_all_nymd_gateway_delegations(
&self,
) -> Result<Vec<mixnet_contract::UnpackedDelegation<RawDelegationData>>, ValidatorClientError>
where
C: CosmWasmClient + Sync,
{
let mut delegations = Vec::new();
let mut start_after = None;
loop {
let mut paged_response = self
.nymd
.get_all_gateway_delegations(
start_after.take(),
self.gateway_delegations_page_limit,
)
.await?;
delegations.append(&mut paged_response.delegations);

if let Some(start_after_res) = paged_response.start_next_after {
start_after = Some(start_after_res)
} else {
break;
}
}

Ok(delegations)
}

pub async fn get_all_nymd_reverse_gateway_delegations(
&self,
delegation_owner: &cosmrs::AccountId,
Expand Down
47 changes: 42 additions & 5 deletions common/client-libs/validator-client/src/nymd/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ use cosmrs::tx::{Fee, Gas};
use cosmwasm_std::Coin;
use mixnet_contract::{
Addr, Delegation, ExecuteMsg, Gateway, GatewayOwnershipResponse, IdentityKey,
LayerDistribution, MixNode, MixOwnershipResponse, PagedGatewayDelegationsResponse,
PagedGatewayResponse, PagedMixDelegationsResponse, PagedMixnodeResponse,
PagedReverseGatewayDelegationsResponse, PagedReverseMixDelegationsResponse, QueryMsg,
StateParams,
LayerDistribution, MixNode, MixOwnershipResponse, PagedAllDelegationsResponse,
PagedGatewayDelegationsResponse, PagedGatewayResponse, PagedMixDelegationsResponse,
PagedMixnodeResponse, PagedReverseGatewayDelegationsResponse,
PagedReverseMixDelegationsResponse, QueryMsg, StateParams,
};
use serde::Serialize;
use std::collections::HashMap;
Expand Down Expand Up @@ -262,6 +262,25 @@ impl<C> NymdClient<C> {
.await
}

/// Gets list of all mixnode delegations on particular page.
pub async fn get_all_mix_delegations_paged(
&self,
// I really hate mixing cosmwasm and cosmos-sdk types here...
start_after: Option<Vec<u8>>,
page_limit: Option<u32>,
) -> Result<PagedAllDelegationsResponse, NymdError>
where
C: CosmWasmClient + Sync,
{
let request = QueryMsg::GetAllMixDelegations {
start_after,
limit: page_limit,
};
self.client
.query_contract_smart(self.contract_address()?, &request)
.await
}

/// Gets list of all the mixnodes on which a particular address delegated.
pub async fn get_reverse_mix_delegations_paged(
&self,
Expand Down Expand Up @@ -300,7 +319,7 @@ impl<C> NymdClient<C> {
.await
}

/// Gets list of all delegations towards particular mixnode on particular page.
/// Gets list of all delegations towards particular gateway on particular page.
pub async fn get_gateway_delegations(
&self,
gateway_identity: IdentityKey,
Expand All @@ -320,6 +339,24 @@ impl<C> NymdClient<C> {
.await
}

/// Gets list of all gateway delegations on particular page.
pub async fn get_all_gateway_delegations(
&self,
start_after: Option<Vec<u8>>,
page_limit: Option<u32>,
) -> Result<PagedAllDelegationsResponse, NymdError>
where
C: CosmWasmClient + Sync,
{
let request = QueryMsg::GetAllGatewayDelegations {
start_after,
limit: page_limit,
};
self.client
.query_contract_smart(self.contract_address()?, &request)
.await
}

/// Gets list of all the gateways on which a particular address delegated.
pub async fn get_reverse_gateway_delegations_paged(
&self,
Expand Down
22 changes: 21 additions & 1 deletion common/mixnet-contract/src/delegation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use std::fmt::Display;

#[derive(Debug, Deserialize, PartialEq, Serialize)]
pub type UnpackedDelegation<T> = (Addr, IdentityKey, T);
neacsu marked this conversation as resolved.
Show resolved Hide resolved

#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)]
pub struct RawDelegationData {
pub amount: Uint128,
pub block_height: u64,
Expand Down Expand Up @@ -144,3 +146,21 @@ impl PagedReverseGatewayDelegationsResponse {
}
}
}

#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)]
pub struct PagedAllDelegationsResponse {
pub delegations: Vec<UnpackedDelegation<RawDelegationData>>,
pub start_next_after: Option<Vec<u8>>,
}

impl PagedAllDelegationsResponse {
pub fn new(
delegations: Vec<UnpackedDelegation<RawDelegationData>>,
start_next_after: Option<Vec<u8>>,
) -> Self {
PagedAllDelegationsResponse {
delegations,
start_next_after,
}
}
}
5 changes: 3 additions & 2 deletions common/mixnet-contract/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ mod types;

pub use cosmwasm_std::{Addr, Coin};
pub use delegation::{
Delegation, PagedGatewayDelegationsResponse, PagedMixDelegationsResponse,
PagedReverseGatewayDelegationsResponse, PagedReverseMixDelegationsResponse, RawDelegationData,
Delegation, PagedAllDelegationsResponse, PagedGatewayDelegationsResponse,
PagedMixDelegationsResponse, PagedReverseGatewayDelegationsResponse,
PagedReverseMixDelegationsResponse, RawDelegationData, UnpackedDelegation,
};
pub use gateway::{Gateway, GatewayBond, GatewayOwnershipResponse, PagedGatewayResponse};
pub use mixnode::{Layer, MixNode, MixNodeBond, MixOwnershipResponse, PagedMixnodeResponse};
Expand Down
8 changes: 8 additions & 0 deletions common/mixnet-contract/src/msg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@ pub enum QueryMsg {
start_after: Option<Addr>,
limit: Option<u32>,
},
GetAllMixDelegations {
start_after: Option<Vec<u8>>,
limit: Option<u32>,
},
GetReverseMixDelegations {
delegation_owner: Addr,
start_after: Option<IdentityKey>,
Expand All @@ -89,6 +93,10 @@ pub enum QueryMsg {
start_after: Option<Addr>,
limit: Option<u32>,
},
GetAllGatewayDelegations {
start_after: Option<Vec<u8>>,
limit: Option<u32>,
},
GetReverseGatewayDelegations {
delegation_owner: Addr,
start_after: Option<IdentityKey>,
Expand Down
77 changes: 21 additions & 56 deletions contracts/mixnet/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,9 @@ pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> Result<QueryResponse, Cont
start_after,
limit,
)?),
QueryMsg::GetAllMixDelegations { start_after, limit } => to_binary(
&queries::query_all_mixnode_delegations_paged(deps, start_after, limit)?,
),
QueryMsg::GetReverseMixDelegations {
delegation_owner,
start_after,
Expand Down Expand Up @@ -183,6 +186,9 @@ pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> Result<QueryResponse, Cont
start_after,
limit,
)?),
QueryMsg::GetAllGatewayDelegations { start_after, limit } => to_binary(
&queries::query_all_gateway_delegations_paged(deps, start_after, limit)?,
),
QueryMsg::GetReverseGatewayDelegations {
delegation_owner,
start_after,
Expand All @@ -207,68 +213,27 @@ pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> Result<QueryResponse, Cont
}

#[entry_point]
pub fn migrate(mut deps: DepsMut, _env: Env, _msg: MigrateMsg) -> Result<Response, ContractError> {
pub fn migrate(deps: DepsMut, env: Env, _msg: MigrateMsg) -> Result<Response, ContractError> {
use crate::storage::{
gateway_delegations, gateway_delegations_read, gateway_delegations_read_old, gateways_read,
mix_delegations, mix_delegations_read, mix_delegations_read_old, mixnodes_read,
all_gateway_delegations_read, all_mix_delegations_read, gateway_delegations,
mix_delegations, reverse_gateway_delegations, reverse_mix_delegations,
};
use crate::transactions::delegations;
use cosmwasm_std::{Order, StdResult};
use mixnet_contract::{GatewayBond, MixNodeBond};

// Read existing delegations data, drop invalid values, and rewrite delegations data with valid data only
fn overwrite_mixnode_delegations_data(
identity: &str,
deps: &mut DepsMut,
) -> Result<(), ContractError> {
let delegations_bucket = mix_delegations_read(deps.storage, identity);
let old_delegations_bucket = mix_delegations_read_old(deps.storage, identity);
let mut delegations_vec = delegations(delegations_bucket)?;
let old_delegations = delegations::<Uint128>(old_delegations_bucket)?;
for delegation in old_delegations {
delegations_vec.push((delegation.0, RawDelegationData::new(delegation.1, 1)))
}

for (key, delegation) in delegations_vec {
mix_delegations(deps.storage, identity).save(&key, &delegation)?;
}
Ok(())
}

fn overwrite_gateway_delegations_data(
identity: &str,
deps: &mut DepsMut,
) -> Result<(), ContractError> {
let delegations_bucket = gateway_delegations_read(deps.storage, identity);
let old_delegations_bucket = gateway_delegations_read_old(deps.storage, identity);
let mut delegations_vec = delegations(delegations_bucket)?;
let old_delegations = delegations::<Uint128>(old_delegations_bucket)?;
for delegation in old_delegations {
delegations_vec.push((delegation.0, RawDelegationData::new(delegation.1, 1)))
}

for (key, delegation) in delegations_vec {
gateway_delegations(deps.storage, identity).save(&key, &delegation)?;
}
Ok(())
let mix_bucket = all_mix_delegations_read::<Uint128>(deps.storage);
let all_delegations = delegations(mix_bucket)?;
for (owner, identity, amount) in all_delegations {
let raw_delegation = RawDelegationData::new(amount, env.block.height);
mix_delegations(deps.storage, &identity).save(owner.as_bytes(), &raw_delegation)?;
reverse_mix_delegations(deps.storage, &owner).save(identity.as_bytes(), &())?;
}

let mixnet_bonds = mixnodes_read(deps.storage)
.range(None, None, Order::Ascending)
.map(|res| res.map(|item| item.1))
.collect::<StdResult<Vec<MixNodeBond>>>()?;

for bond in mixnet_bonds {
overwrite_mixnode_delegations_data(bond.identity(), &mut deps)?;
}

let gateway_bonds = gateways_read(deps.storage)
.range(None, None, Order::Ascending)
.map(|res| res.map(|item| item.1))
.collect::<StdResult<Vec<GatewayBond>>>()?;

for bond in gateway_bonds {
overwrite_gateway_delegations_data(bond.identity(), &mut deps)?;
let gateway_bucket = all_gateway_delegations_read::<Uint128>(deps.storage);
let all_delegations = delegations(gateway_bucket)?;
for (owner, identity, amount) in all_delegations {
let raw_delegation = RawDelegationData::new(amount, env.block.height);
gateway_delegations(deps.storage, &identity).save(owner.as_bytes(), &raw_delegation)?;
reverse_gateway_delegations(deps.storage, &owner).save(identity.as_bytes(), &())?;
}

Ok(Default::default())
Expand Down
Loading