Compare commits

...

11 Commits

Author SHA1 Message Date
Jędrzej Stuczyński 7892066f88 Added code for gateway migration 2022-09-22 15:46:55 +01:00
Jędrzej Stuczyński 22518e277e Paged query for obtaining all delegatons 2022-09-22 09:03:31 +01:00
Jędrzej Stuczyński 53dc0a52a1 Removed mix_denom from vesting migration 2022-09-06 16:41:38 +01:00
Jędrzej Stuczyński 948c3e6423 Merge with develop 2022-09-06 16:24:09 +01:00
Jędrzej Stuczyński e006f2f4a4 Fixes to vesting-related migration 2022-09-02 14:45:11 +01:00
Jędrzej Stuczyński 1ba8729813 Disabled vesting delegations queries 2022-08-30 15:21:22 +01:00
Jędrzej Stuczyński 80c626da83 Added profit margin percent in migration message 2022-08-30 15:15:54 +01:00
Jędrzej Stuczyński 4cfea04475 Updated mix_id to correctly use u32 as opposed to u64 2022-08-30 15:15:54 +01:00
Jędrzej Stuczyński 3d9ee1e0c1 Renamed v2 execution messages 2022-08-30 15:15:54 +01:00
Jędrzej Stuczyński 499ddbd362 Updating vesting contract storage 2022-08-30 15:15:54 +01:00
Jędrzej Stuczyński 58b23e6ee4 Initial mixnet v1->v2 migration code 2022-08-30 15:15:11 +01:00
11 changed files with 907 additions and 411 deletions
@@ -22,9 +22,9 @@ use mixnet_contract_common::{
ContractStateParams, Delegation, ExecuteMsg, Gateway, GatewayBond, GatewayBondResponse,
GatewayOwnershipResponse, IdentityKey, Interval, LayerDistribution, MixNode, MixNodeBond,
MixOwnershipResponse, MixnetContractVersion, MixnodeBondResponse,
MixnodeRewardingStatusResponse, PagedDelegatorDelegationsResponse, PagedGatewayResponse,
PagedMixDelegationsResponse, PagedMixnodeResponse, PagedRewardedSetResponse, QueryMsg,
RewardedSetUpdateDetails,
MixnodeRewardingStatusResponse, PagedAllDelegationsResponse, PagedDelegatorDelegationsResponse,
PagedGatewayResponse, PagedMixDelegationsResponse, PagedMixnodeResponse,
PagedRewardedSetResponse, QueryMsg, RewardedSetUpdateDetails,
};
use serde::{Deserialize, Serialize};
use std::convert::TryInto;
@@ -838,6 +838,22 @@ impl<C> NymdClient<C> {
.await
}
pub async fn get_all_delegations_paged(
&self,
start_after: Option<(IdentityKey, Vec<u8>, u64)>,
) -> Result<PagedAllDelegationsResponse, NymdError>
where
C: CosmWasmClient + Sync,
{
let request = QueryMsg::GetAllDelegationValuesPaged {
start_after,
limit: None,
};
self.client
.query_contract_smart(self.mixnet_contract_address(), &request)
.await
}
/// Checks value of delegation of given client towards particular mixnode.
pub async fn get_delegation_details(
&self,
@@ -2,8 +2,9 @@
// SPDX-License-Identifier: Apache-2.0
use crate::reward_params::NodeRewardParams;
use crate::ContractStateParams;
use crate::{ContractStateParams, Layer, SphinxKey};
use crate::{Gateway, IdentityKey, MixNode};
use cosmwasm_std::{Addr, Coin};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
@@ -122,6 +123,10 @@ pub enum ExecuteMsg {
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum QueryMsg {
GetAllDelegationValuesPaged {
start_after: Option<(IdentityKey, Vec<u8>, u64)>,
limit: Option<u32>,
},
GetBlacklistedNodes {},
GetCurrentOperatorCost {},
GetRewardingValidatorAddress {},
@@ -213,16 +218,147 @@ pub enum QueryMsg {
},
}
// all of those `serde rename` are here to reduce the rpc response size to bare minimum
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
#[serde(rename_all = "snake_case")]
#[serde(rename = "op")]
pub enum V2MigrationOperation {
#[serde(rename = "m1")]
MigrateOperator {
#[serde(rename = "a1")]
node_identity: String,
},
#[serde(rename = "m2")]
MigrateDelegator {
#[serde(rename = "a1")]
address: Addr,
#[serde(rename = "a2")]
node_identity: String,
#[serde(rename = "a3")]
proxy: Option<Addr>,
#[serde(rename = "a4")]
new_mix_id: Option<u32>,
},
#[serde(rename = "m3")]
RemoveOperator {
#[serde(rename = "a1")]
node_identity: String,
},
#[serde(rename = "m4")]
RemoveDelegator {
#[serde(rename = "a1")]
address: Addr,
#[serde(rename = "a2")]
node_identity: String,
#[serde(rename = "a3")]
proxy: Option<Addr>,
},
#[serde(rename = "m5")]
MigrateGateway {
#[serde(rename = "a1")]
node_identity: String,
},
#[serde(rename = "m6")]
RemoveGateway {
#[serde(rename = "a1")]
node_identity: String,
},
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum SpecialV2ExecuteMsg {
#[serde(rename = "m1")]
SaveOperator {
#[serde(rename = "a1")]
host: String,
#[serde(rename = "a2")]
mix_port: u16,
#[serde(rename = "a3")]
verloc_port: u16,
#[serde(rename = "a4")]
http_api_port: u16,
#[serde(rename = "a5")]
sphinx_key: SphinxKey,
#[serde(rename = "a6")]
identity_key: IdentityKey,
#[serde(rename = "a7")]
version: String,
#[serde(rename = "a8")]
pledge_amount: Coin,
#[serde(rename = "a9")]
owner: Addr,
#[serde(rename = "a10")]
block_height: u64,
#[serde(rename = "a11")]
profit_margin_percent: u8,
#[serde(rename = "a12")]
proxy: Option<Addr>,
},
#[serde(rename = "m2")]
SaveDelegation {
#[serde(rename = "a1")]
owner: Addr,
#[serde(rename = "a2")]
mix_id: u32,
#[serde(rename = "a3")]
amount: Coin,
#[serde(rename = "a4")]
block_height: u64,
#[serde(rename = "a5")]
proxy: Option<Addr>,
},
#[serde(rename = "m3")]
SaveGateway {
#[serde(rename = "a1")]
pledge_amount: Coin,
#[serde(rename = "a2")]
owner: Addr,
#[serde(rename = "a3")]
block_height: u64,
#[serde(rename = "a4")]
gateway: Gateway,
#[serde(rename = "a5")]
proxy: Option<Addr>,
},
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub struct MigrateMsg {
pub nodes_to_remove: Option<Vec<NodeToRemove>>,
}
impl MigrateMsg {
pub fn nodes_to_remove(&self) -> Vec<NodeToRemove> {
self.nodes_to_remove.clone().unwrap_or_default()
}
pub v2_contract_address: String,
pub vesting_contract_address: String,
pub operations: Vec<V2MigrationOperation>,
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
@@ -12,9 +12,7 @@ pub struct InitMsg {
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub struct MigrateMsg {
pub mix_denom: String,
}
pub struct MigrateMsg {}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema, Default)]
pub struct VestingSpecification {
@@ -119,10 +117,11 @@ pub enum ExecuteMsg {
UpdateLockedPledgeCap {
amount: Uint128,
},
MigrateHeightsToTimestamps {
account_id: u32,
mix_identity: String,
height_timestamp_map: Vec<(u64, u64)>,
AuthorisedUpdateToV2 {
owner: String,
node_identity: IdentityKey,
mix_id: u32,
},
}
+218 -218
View File
@@ -7,6 +7,7 @@ use crate::delegations::queries::query_mixnode_delegation;
use crate::delegations::queries::{
query_mixnode_delegations_paged, query_pending_delegation_events,
};
use crate::delegations::storage::delegations;
use crate::error::ContractError;
use crate::gateways::queries::query_owns_gateway;
use crate::gateways::queries::{query_gateway_bond, query_gateways_paged};
@@ -24,17 +25,19 @@ use crate::mixnet_contract_settings::storage as mixnet_params_storage;
use crate::mixnet_contract_settings::transactions::try_update_rewarding_validator_address;
use crate::mixnodes::bonding_queries as mixnode_queries;
use crate::mixnodes::bonding_queries::{
query_checkpoints_for_mixnode, query_mixnode_at_height, query_mixnodes_paged,
query_checkpoints_for_mixnode, query_mixnode_at_height, query_mixnode_bond,
query_mixnodes_paged,
};
use crate::mixnodes::layer_queries::query_layer_distribution;
use crate::mixnodes::transactions::_try_remove_mixnode;
use crate::queued_migrations::v2_migration;
use crate::rewards::queries::{
query_circulating_supply, query_reward_pool, query_rewarding_status, query_staking_supply,
};
use crate::rewards::storage as rewards_storage;
use cosmwasm_std::{
entry_point, to_binary, Addr, Api, Deps, DepsMut, Env, MessageInfo, QueryResponse, Response,
Storage, Uint128,
Storage, SubMsg, Uint128,
};
use mixnet_contract_common::{
ContractStateParams, ExecuteMsg, InstantiateMsg, MigrateMsg, NodeToRemove, QueryMsg,
@@ -113,6 +116,7 @@ pub fn execute(
msg: ExecuteMsg,
) -> Result<Response, ContractError> {
match msg {
// we must be able to perform universal compound alongside reconcile
ExecuteMsg::CompoundReward {
operator,
delegator,
@@ -126,215 +130,217 @@ pub fn execute(
mix_identity,
proxy,
),
ExecuteMsg::UpdateRewardingValidatorAddress { address } => {
try_update_rewarding_validator_address(deps, info, address)
}
ExecuteMsg::InitEpoch {} => try_init_epoch(info, deps.storage, env),
ExecuteMsg::BondMixnode {
mix_node,
owner_signature,
} => crate::mixnodes::transactions::try_add_mixnode(
deps,
env,
info,
mix_node,
owner_signature,
),
ExecuteMsg::UnbondMixnode {} => {
crate::mixnodes::transactions::try_remove_mixnode(&env, deps.storage, deps.api, info)
}
ExecuteMsg::UpdateMixnodeConfig {
profit_margin_percent,
} => crate::mixnodes::transactions::try_update_mixnode_config(
deps,
env,
info,
profit_margin_percent,
),
ExecuteMsg::UpdateMixnodeConfigOnBehalf {
profit_margin_percent,
owner,
} => crate::mixnodes::transactions::try_update_mixnode_config_on_behalf(
deps,
env,
info,
profit_margin_percent,
owner,
),
ExecuteMsg::BondGateway {
gateway,
owner_signature,
} => crate::gateways::transactions::try_add_gateway(
deps,
env,
info,
gateway,
owner_signature,
),
ExecuteMsg::UnbondGateway {} => {
crate::gateways::transactions::try_remove_gateway(deps, info)
}
ExecuteMsg::UpdateContractStateParams(params) => {
crate::mixnet_contract_settings::transactions::try_update_contract_settings(
deps, info, params,
)
}
ExecuteMsg::RewardMixnode { identity, params } => {
crate::rewards::transactions::try_reward_mixnode(deps, env, info, identity, params)
}
ExecuteMsg::DelegateToMixnode { mix_identity } => {
crate::delegations::transactions::try_delegate_to_mixnode(deps, env, info, mix_identity)
}
ExecuteMsg::UndelegateFromMixnode { mix_identity } => {
crate::delegations::transactions::try_remove_delegation_from_mixnode(
deps,
env,
info,
mix_identity,
)
}
// ExecuteMsg::RewardNextMixDelegators {
// mix_identity,
// interval_id,
// } => crate::rewards::transactions::try_reward_next_mixnode_delegators(
// deps,
// info,
// mix_identity,
// interval_id,
// ),
ExecuteMsg::DelegateToMixnodeOnBehalf {
mix_identity,
delegate,
} => crate::delegations::transactions::try_delegate_to_mixnode_on_behalf(
deps,
env,
info,
mix_identity,
delegate,
),
ExecuteMsg::UndelegateFromMixnodeOnBehalf {
mix_identity,
delegate,
} => crate::delegations::transactions::try_remove_delegation_from_mixnode_on_behalf(
deps,
env,
info,
mix_identity,
delegate,
),
ExecuteMsg::BondMixnodeOnBehalf {
mix_node,
owner,
owner_signature,
} => crate::mixnodes::transactions::try_add_mixnode_on_behalf(
deps,
env,
info,
mix_node,
owner,
owner_signature,
),
ExecuteMsg::UnbondMixnodeOnBehalf { owner } => {
crate::mixnodes::transactions::try_remove_mixnode_on_behalf(
&env,
deps.storage,
deps.api,
info,
owner,
)
}
ExecuteMsg::BondGatewayOnBehalf {
gateway,
owner,
owner_signature,
} => crate::gateways::transactions::try_add_gateway_on_behalf(
deps,
env,
info,
gateway,
owner,
owner_signature,
),
ExecuteMsg::UnbondGatewayOnBehalf { owner } => {
crate::gateways::transactions::try_remove_gateway_on_behalf(deps, info, owner)
}
ExecuteMsg::WriteRewardedSet {
rewarded_set,
expected_active_set_size,
} => crate::interval::transactions::try_write_rewarded_set(
deps,
env,
info,
rewarded_set,
expected_active_set_size,
),
ExecuteMsg::AdvanceCurrentEpoch {} => crate::interval::transactions::try_advance_epoch(
env,
deps.storage,
info.sender.to_string(),
),
ExecuteMsg::CompoundDelegatorReward { mix_identity } => {
crate::rewards::transactions::try_compound_delegator_reward(
deps,
env,
info,
mix_identity,
)
}
ExecuteMsg::CompoundOperatorReward {} => {
crate::rewards::transactions::try_compound_operator_reward(deps, env, info)
}
ExecuteMsg::CompoundDelegatorRewardOnBehalf {
owner,
mix_identity,
} => crate::rewards::transactions::try_compound_delegator_reward_on_behalf(
deps,
env,
info,
owner,
mix_identity,
),
ExecuteMsg::CompoundOperatorRewardOnBehalf { owner } => {
crate::rewards::transactions::try_compound_operator_reward_on_behalf(
deps, env, info, owner,
)
}
ExecuteMsg::ReconcileDelegations {} => {
crate::delegations::transactions::try_reconcile_all_delegation_events(deps)
}
ExecuteMsg::CheckpointMixnodes {} => {
crate::mixnodes::transactions::try_checkpoint_mixnodes(
deps.storage,
env.block.height,
info,
)
}
ExecuteMsg::ClaimOperatorReward {} => {
crate::rewards::transactions::try_claim_operator_reward(deps, &env, &info)
}
ExecuteMsg::ClaimOperatorRewardOnBehalf { owner } => {
crate::rewards::transactions::try_claim_operator_reward_on_behalf(
deps, &env, &info, owner,
)
}
ExecuteMsg::ClaimDelegatorReward { mix_identity } => {
crate::rewards::transactions::try_claim_delegator_reward(
deps,
&env,
&info,
&mix_identity,
)
}
ExecuteMsg::ClaimDelegatorRewardOnBehalf {
mix_identity,
owner,
} => crate::rewards::transactions::try_claim_delegator_reward_on_behalf(
deps,
&env,
&info,
owner,
&mix_identity,
),
_ => Err(ContractError::MaintenanceMode),
// ExecuteMsg::UpdateRewardingValidatorAddress { address } => {
// try_update_rewarding_validator_address(deps, info, address)
// }
// ExecuteMsg::InitEpoch {} => try_init_epoch(info, deps.storage, env),
// ExecuteMsg::BondMixnode {
// mix_node,
// owner_signature,
// } => crate::mixnodes::transactions::try_add_mixnode(
// deps,
// env,
// info,
// mix_node,
// owner_signature,
// ),
// ExecuteMsg::UnbondMixnode {} => {
// crate::mixnodes::transactions::try_remove_mixnode(&env, deps.storage, deps.api, info)
// }
// ExecuteMsg::UpdateMixnodeConfig {
// profit_margin_percent,
// } => crate::mixnodes::transactions::try_update_mixnode_config(
// deps,
// env,
// info,
// profit_margin_percent,
// ),
// ExecuteMsg::UpdateMixnodeConfigOnBehalf {
// profit_margin_percent,
// owner,
// } => crate::mixnodes::transactions::try_update_mixnode_config_on_behalf(
// deps,
// env,
// info,
// profit_margin_percent,
// owner,
// ),
// ExecuteMsg::BondGateway {
// gateway,
// owner_signature,
// } => crate::gateways::transactions::try_add_gateway(
// deps,
// env,
// info,
// gateway,
// owner_signature,
// ),
// ExecuteMsg::UnbondGateway {} => {
// crate::gateways::transactions::try_remove_gateway(deps, info)
// }
// ExecuteMsg::UpdateContractStateParams(params) => {
// crate::mixnet_contract_settings::transactions::try_update_contract_settings(
// deps, info, params,
// )
// }
// ExecuteMsg::RewardMixnode { identity, params } => {
// crate::rewards::transactions::try_reward_mixnode(deps, env, info, identity, params)
// }
// ExecuteMsg::DelegateToMixnode { mix_identity } => {
// crate::delegations::transactions::try_delegate_to_mixnode(deps, env, info, mix_identity)
// }
// ExecuteMsg::UndelegateFromMixnode { mix_identity } => {
// crate::delegations::transactions::try_remove_delegation_from_mixnode(
// deps,
// env,
// info,
// mix_identity,
// )
// }
// // ExecuteMsg::RewardNextMixDelegators {
// // mix_identity,
// // interval_id,
// // } => crate::rewards::transactions::try_reward_next_mixnode_delegators(
// // deps,
// // info,
// // mix_identity,
// // interval_id,
// // ),
// ExecuteMsg::DelegateToMixnodeOnBehalf {
// mix_identity,
// delegate,
// } => crate::delegations::transactions::try_delegate_to_mixnode_on_behalf(
// deps,
// env,
// info,
// mix_identity,
// delegate,
// ),
// ExecuteMsg::UndelegateFromMixnodeOnBehalf {
// mix_identity,
// delegate,
// } => crate::delegations::transactions::try_remove_delegation_from_mixnode_on_behalf(
// deps,
// env,
// info,
// mix_identity,
// delegate,
// ),
// ExecuteMsg::BondMixnodeOnBehalf {
// mix_node,
// owner,
// owner_signature,
// } => crate::mixnodes::transactions::try_add_mixnode_on_behalf(
// deps,
// env,
// info,
// mix_node,
// owner,
// owner_signature,
// ),
// ExecuteMsg::UnbondMixnodeOnBehalf { owner } => {
// crate::mixnodes::transactions::try_remove_mixnode_on_behalf(
// &env,
// deps.storage,
// deps.api,
// info,
// owner,
// )
// }
// ExecuteMsg::BondGatewayOnBehalf {
// gateway,
// owner,
// owner_signature,
// } => crate::gateways::transactions::try_add_gateway_on_behalf(
// deps,
// env,
// info,
// gateway,
// owner,
// owner_signature,
// ),
// ExecuteMsg::UnbondGatewayOnBehalf { owner } => {
// crate::gateways::transactions::try_remove_gateway_on_behalf(deps, info, owner)
// }
// ExecuteMsg::WriteRewardedSet {
// rewarded_set,
// expected_active_set_size,
// } => crate::interval::transactions::try_write_rewarded_set(
// deps,
// env,
// info,
// rewarded_set,
// expected_active_set_size,
// ),
// ExecuteMsg::AdvanceCurrentEpoch {} => crate::interval::transactions::try_advance_epoch(
// env,
// deps.storage,
// info.sender.to_string(),
// ),
// ExecuteMsg::CompoundDelegatorReward { mix_identity } => {
// crate::rewards::transactions::try_compound_delegator_reward(
// deps,
// env,
// info,
// mix_identity,
// )
// }
// ExecuteMsg::CompoundOperatorReward {} => {
// crate::rewards::transactions::try_compound_operator_reward(deps, env, info)
// }
// ExecuteMsg::CompoundDelegatorRewardOnBehalf {
// owner,
// mix_identity,
// } => crate::rewards::transactions::try_compound_delegator_reward_on_behalf(
// deps,
// env,
// info,
// owner,
// mix_identity,
// ),
// ExecuteMsg::CompoundOperatorRewardOnBehalf { owner } => {
// crate::rewards::transactions::try_compound_operator_reward_on_behalf(
// deps, env, info, owner,
// )
// }
//
// ExecuteMsg::CheckpointMixnodes {} => {
// crate::mixnodes::transactions::try_checkpoint_mixnodes(
// deps.storage,
// env.block.height,
// info,
// )
// }
// ExecuteMsg::ClaimOperatorReward {} => {
// crate::rewards::transactions::try_claim_operator_reward(deps, &env, &info)
// }
// ExecuteMsg::ClaimOperatorRewardOnBehalf { owner } => {
// crate::rewards::transactions::try_claim_operator_reward_on_behalf(
// deps, &env, &info, owner,
// )
// }
// ExecuteMsg::ClaimDelegatorReward { mix_identity } => {
// crate::rewards::transactions::try_claim_delegator_reward(
// deps,
// &env,
// &info,
// &mix_identity,
// )
// }
// ExecuteMsg::ClaimDelegatorRewardOnBehalf {
// mix_identity,
// owner,
// } => crate::rewards::transactions::try_claim_delegator_reward_on_behalf(
// deps,
// &env,
// &info,
// owner,
// &mix_identity,
// ),
}
}
@@ -466,6 +472,9 @@ pub fn query(deps: Deps<'_>, env: Env, msg: QueryMsg) -> Result<QueryResponse, C
mix_identity,
height,
} => to_binary(&query_mixnode_at_height(deps, mix_identity, height)?),
QueryMsg::GetAllDelegationValuesPaged { start_after, limit } => to_binary(
&crate::delegations::queries::query_all_delegations_paged(deps, start_after, limit)?,
),
};
Ok(query_res?)
@@ -508,16 +517,7 @@ fn remove_malicious_node(
#[entry_point]
pub fn migrate(deps: DepsMut<'_>, env: Env, msg: MigrateMsg) -> Result<Response, ContractError> {
let mut response = Response::new();
for node in msg.nodes_to_remove().iter() {
let mut sub_response = remove_malicious_node(deps.storage, deps.api, &env, node)
.unwrap_or_else(|_| panic!("Could not remove node: {:?}", node));
response.messages.append(&mut sub_response.messages);
response.attributes.append(&mut sub_response.attributes);
response.events.append(&mut sub_response.events);
}
Ok(response)
v2_migration(deps, env, msg)
}
#[cfg(test)]
+26 -4
View File
@@ -8,10 +8,7 @@ use cosmwasm_std::StdResult;
use cosmwasm_std::{Api, Deps, Storage};
use cw_storage_plus::{Bound, PrimaryKey};
use mixnet_contract_common::mixnode::DelegationEvent;
use mixnet_contract_common::{
delegation, Delegation, IdentityKey, PagedDelegatorDelegationsResponse,
PagedMixDelegationsResponse,
};
use mixnet_contract_common::{delegation, Delegation, IdentityKey, PagedAllDelegationsResponse, PagedDelegatorDelegationsResponse, PagedMixDelegationsResponse};
pub(crate) fn query_pending_delegation_events(
deps: Deps<'_>,
@@ -80,6 +77,31 @@ pub fn query_all_delegation_keys(storage: &dyn Storage) -> Result<Vec<String>, C
use std::collections::HashSet;
pub(crate) fn query_all_delegations_paged(
deps: Deps<'_>,
start_after: Option<(IdentityKey, Vec<u8>, u64)>,
limit: Option<u32>,
) -> StdResult<PagedAllDelegationsResponse> {
let limit = limit
.unwrap_or(300)
.min(500) as usize;
let start = start_after.map(Bound::exclusive);
let delegations = storage::delegations()
.range(deps.storage, start, None, Order::Ascending)
.take(limit)
.map(|res| res.map(|item| item.1))
.collect::<StdResult<Vec<_>>>()?;
let start_next_after = delegations.last().map(|del| del.storage_key());
Ok(PagedAllDelegationsResponse::new(
delegations,
start_next_after,
))
}
// This should only be exposed directly on the contract via nymd binary, not through the nymd clients
pub fn debug_query_all_delegation_values(
storage: &dyn Storage,
+3
View File
@@ -185,4 +185,7 @@ pub enum ContractError {
#[error("Mixnode {identity} has been blacklisted on the network")]
MixnodeBlacklisted { identity: String },
#[error("Contract is currently set to the maintenance mode - all transactions are temporarily disabled")]
MaintenanceMode,
}
+302
View File
@@ -1,2 +1,304 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::delegations::queries::query_mixnode_delegation;
use crate::delegations::storage::delegations;
use crate::error::ContractError;
use crate::gateways::storage::gateways;
use crate::mixnodes::storage::mixnodes;
use cosmwasm_std::{wasm_execute, Addr, BankMsg, DepsMut, Env, Response, SubMsg};
use cw_storage_plus::Map;
use mixnet_contract_common::delegation::generate_storage_key;
use mixnet_contract_common::{IdentityKey, MigrateMsg, SpecialV2ExecuteMsg, V2MigrationOperation};
use vesting_contract_common::messages::ExecuteMsg as VestingContractExecuteMsg;
const MIGRATED_MIXNODES: Map<IdentityKey, u8> = Map::new("migrated-mixnodes");
const MIGRATED_GATEWAYS: Map<IdentityKey, u8> = Map::new("migrated-gateways");
type OwnerXorProxy = Vec<u8>;
const MIGRATED_DELEGATES: Map<(IdentityKey, OwnerXorProxy), u8> = Map::new("migrated-delegates");
fn migrate_operator(
deps: &mut DepsMut,
v2_mixnet_contract: &str,
node_identity: String,
response: &mut Response,
) -> Result<(), ContractError> {
if MIGRATED_MIXNODES.has(deps.storage, node_identity.clone()) {
// again, panic here because this should never occur and it's incredible dangerous to let it happen
panic!("mixnode {} has already been migrated!", node_identity);
}
MIGRATED_MIXNODES.save(deps.storage, node_identity.clone(), &1u8)?;
let bond = mixnodes()
.load(deps.storage, &node_identity)
.expect("failed to read mixnode bond");
let pledge = bond.pledge_amount.clone();
let v2_message = SpecialV2ExecuteMsg::SaveOperator {
host: bond.mix_node.host,
mix_port: bond.mix_node.mix_port,
verloc_port: bond.mix_node.verloc_port,
http_api_port: bond.mix_node.http_api_port,
sphinx_key: bond.mix_node.sphinx_key,
identity_key: bond.mix_node.identity_key,
version: bond.mix_node.version,
pledge_amount: bond.pledge_amount,
owner: bond.owner,
block_height: bond.block_height,
profit_margin_percent: bond.mix_node.profit_margin_percent,
proxy: bond.proxy,
};
// TODO: do we need separate BankMsg here, or can we just use 'funds' here directly?
let wasm_msg = wasm_execute(v2_mixnet_contract, &v2_message, vec![pledge])
.expect("failed to serialize mixnode migration msg");
response.messages.push(SubMsg::new(wasm_msg));
Ok(())
}
fn migrate_gateway(
deps: &mut DepsMut,
v2_mixnet_contract: &str,
node_identity: String,
response: &mut Response,
) -> Result<(), ContractError> {
if MIGRATED_GATEWAYS.has(deps.storage, node_identity.clone()) {
// again, panic here because this should never occur and it's incredible dangerous to let it happen
panic!("gateway {} has already been migrated!", node_identity);
}
MIGRATED_GATEWAYS.save(deps.storage, node_identity.clone(), &1u8)?;
let bond = gateways()
.load(deps.storage, &node_identity)
.expect("failed to read gateway bond");
let pledge = bond.pledge_amount.clone();
let v2_message = SpecialV2ExecuteMsg::SaveGateway {
pledge_amount: bond.pledge_amount,
owner: bond.owner,
block_height: bond.block_height,
gateway: bond.gateway,
proxy: bond.proxy,
};
// TODO: do we need separate BankMsg here, or can we just use 'funds' here directly?
let wasm_msg = wasm_execute(v2_mixnet_contract, &v2_message, vec![pledge])
.expect("failed to serialize gateway migration msg");
response.messages.push(SubMsg::new(wasm_msg));
Ok(())
}
fn is_proxy_vesting(proxy: Option<&Addr>, vesting_contract: &str) -> bool {
if let Some(proxy) = proxy {
// bypass for my local network where I just imported contract state to fresh contract
// return true;
if proxy.as_ref() == vesting_contract {
return true;
}
}
false
}
fn migrate_delegator(
deps: &mut DepsMut,
v2_mixnet_contract: &str,
vesting_contract: &str,
address: Addr,
node_identity: String,
proxy: Option<Addr>,
new_mix_id: Option<u32>,
response: &mut Response,
) -> Result<(), ContractError> {
let owner_proxy = generate_storage_key(&address, proxy.as_ref());
let storage_key = (node_identity.clone(), owner_proxy);
if MIGRATED_DELEGATES.has(deps.storage, storage_key.clone()) {
// again, panic here because this should never occur and it's incredible dangerous to let it happen
panic!(
"delegator {}/{} has already been migrated!",
address, node_identity
);
}
MIGRATED_DELEGATES.save(deps.storage, storage_key, &1u8)?;
// there should only be one (as we ensured it during previous migration steps, if not, then somebody is not following the migration instructions
// and we're in an inconsistent state)
// also this entry MUST exist as we're explicitly migrating this one
let mut delegation = query_mixnode_delegation(
deps.storage,
deps.api,
node_identity.clone(),
address.clone().into_string(),
proxy.map(Addr::into_string),
)
.expect("specified delegation doesn't exist!!");
if delegation.len() != 1 {
panic!("the universal compound hasn't been run prior to this migration!!")
}
// take ownership of the one and only entry
let delegation = delegation.pop().unwrap();
// if mix_id is `None`, it means target mixnode doesn't exist anymore -> return the tokens
// otherwise attempt to migrate it into the new contract
if let Some(migrated_mix_id) = new_mix_id {
if is_proxy_vesting(delegation.proxy.as_ref(), vesting_contract) {
let vesting_update = VestingContractExecuteMsg::AuthorisedUpdateToV2 {
owner: address.into_string(),
node_identity,
mix_id: migrated_mix_id,
};
let wasm_msg = wasm_execute(vesting_contract, &vesting_update, vec![])
.expect("failed to serialize vesting migration msg");
response.messages.push(SubMsg::new(wasm_msg));
}
let stake = delegation.amount.clone();
let v2_message = SpecialV2ExecuteMsg::SaveDelegation {
owner: delegation.owner,
mix_id: migrated_mix_id,
amount: delegation.amount,
block_height: delegation.block_height,
proxy: delegation.proxy,
};
let wasm_msg = wasm_execute(v2_mixnet_contract, &v2_message, vec![stake])
.expect("failed to serialize mixnode migration msg");
response.messages.push(SubMsg::new(wasm_msg));
} else {
// if the specified proxy matches the vesting contract address -> treat it as "proper" undelegation
// and send tokens back there
if is_proxy_vesting(delegation.proxy.as_ref(), vesting_contract) {
let vesting_track = VestingContractExecuteMsg::TrackUndelegation {
owner: delegation.owner.to_string(),
mix_identity: delegation.node_identity.clone(),
amount: delegation.amount.clone(),
};
let wasm_msg = wasm_execute(vesting_contract, &vesting_track, vec![delegation.amount])?;
response.messages.push(SubMsg::new(wasm_msg));
} else {
let to_address = delegation.proxy.unwrap_or(delegation.owner).into_string();
let return_tokens = BankMsg::Send {
to_address,
amount: vec![delegation.amount],
};
response.messages.push(SubMsg::new(return_tokens));
}
}
Ok(())
}
fn remove_operator(
deps: &mut DepsMut,
env: &Env,
node_identity: String,
) -> Result<(), ContractError> {
if !MIGRATED_MIXNODES.has(deps.storage, node_identity.clone()) {
// again, panic here because this should never occur and it's incredible dangerous to let it happen
panic!(
"attempted to remove mixnode {} without prior migration!",
node_identity
);
}
mixnodes().remove(deps.storage, &node_identity, env.block.height)?;
Ok(())
}
fn remove_gateway(deps: &mut DepsMut, node_identity: String) -> Result<(), ContractError> {
if !MIGRATED_GATEWAYS.has(deps.storage, node_identity.clone()) {
// again, panic here because this should never occur and it's incredible dangerous to let it happen
panic!(
"attempted to remove gateway {} without prior migration!",
node_identity
);
}
gateways().remove(deps.storage, &node_identity)?;
Ok(())
}
fn remove_delegator(
deps: &mut DepsMut,
address: Addr,
node_identity: String,
proxy: Option<Addr>,
) -> Result<(), ContractError> {
let owner_proxy = generate_storage_key(&address, proxy.as_ref());
let storage_key = (node_identity.clone(), owner_proxy);
if !MIGRATED_DELEGATES.has(deps.storage, storage_key.clone()) {
// again, panic here because this should never occur and it's incredible dangerous to let it happen
panic!(
"attempted to remove delegator {}/{} without prior migration!",
address, node_identity
);
}
let height = delegations()
.prefix(storage_key.clone())
.keys(deps.storage, None, None, cosmwasm_std::Order::Ascending)
.next()
.unwrap()
.unwrap();
delegations().remove(deps.storage, (storage_key.0, storage_key.1, height))?;
Ok(())
}
pub fn v2_migration(
mut deps: DepsMut<'_>,
env: Env,
msg: MigrateMsg,
) -> Result<Response, ContractError> {
let mut response = Response::new();
// note: we're explicitly failing on failures here because we expect EVERYTHING we migrate to exist
for op in msg.operations {
match op {
V2MigrationOperation::MigrateOperator { node_identity } => {
migrate_operator(
&mut deps,
&msg.v2_contract_address,
node_identity,
&mut response,
)?;
}
V2MigrationOperation::MigrateGateway { node_identity } => {
migrate_gateway(
&mut deps,
&msg.v2_contract_address,
node_identity,
&mut response,
)?;
}
V2MigrationOperation::MigrateDelegator {
address,
node_identity,
proxy,
new_mix_id,
} => migrate_delegator(
&mut deps,
&msg.v2_contract_address,
&msg.vesting_contract_address,
address,
node_identity,
proxy,
new_mix_id,
&mut response,
)?,
V2MigrationOperation::RemoveOperator { node_identity } => {
remove_operator(&mut deps, &env, node_identity)?;
}
V2MigrationOperation::RemoveDelegator {
address,
node_identity,
proxy,
} => remove_delegator(&mut deps, address, node_identity, proxy)?,
V2MigrationOperation::RemoveGateway { node_identity } => {
remove_gateway(&mut deps, node_identity)?
}
}
}
Ok(response)
}
+152 -148
View File
@@ -1,15 +1,15 @@
use crate::errors::ContractError;
use crate::storage::{
account_from_address, locked_pledge_cap, remove_delegation, save_delegation,
update_locked_pledge_cap, BlockTimestampSecs, ADMIN, DELEGATIONS, MIXNET_CONTRACT_ADDRESS,
MIX_DENOM,
update_locked_pledge_cap, BlockTimestampSecs, NodeId, ADMIN, DELEGATIONS,
MIXNET_CONTRACT_ADDRESS, MIX_DENOM, OLD_DELEGATIONS,
};
use crate::traits::{
DelegatingAccount, GatewayBondingAccount, MixnodeBondingAccount, VestingAccount,
};
use crate::vesting::{populate_vesting_periods, Account};
use cosmwasm_std::{
coin, entry_point, to_binary, BankMsg, Coin, Deps, DepsMut, Env, MessageInfo, Order,
coin, entry_point, to_binary, BankMsg, Coin, Deps, DepsMut, Env, Event, MessageInfo, Order,
QueryResponse, Response, StdResult, Timestamp, Uint128,
};
use cw_storage_plus::Bound;
@@ -49,96 +49,122 @@ pub fn migrate(_deps: DepsMut<'_>, _env: Env, _msg: MigrateMsg) -> Result<Respon
Ok(Response::default())
}
fn update_delegation_to_v2(
deps: DepsMut<'_>,
info: MessageInfo,
owner: String,
node_identity: String,
mix_id: NodeId,
) -> Result<Response, ContractError> {
if info.sender != MIXNET_CONTRACT_ADDRESS.load(deps.storage)? {
return Err(ContractError::NotMixnetContract(info.sender));
}
// this MUST succeed since we know this delegation was created via vesting contract...
let account = account_from_address(&owner, deps.storage, deps.api)?;
let storage_prefix = (account.storage_key(), node_identity.clone());
let old_data = OLD_DELEGATIONS
.prefix(storage_prefix.clone())
.range(deps.storage, None, None, Order::Ascending)
.collect::<StdResult<Vec<_>>>()?;
for (timestamp, amount) in old_data {
OLD_DELEGATIONS.remove(
deps.storage,
(storage_prefix.0, storage_prefix.1.clone(), timestamp),
);
DELEGATIONS.save(deps.storage, (storage_prefix.0, mix_id, timestamp), &amount)?;
}
Ok(Response::new())
}
#[entry_point]
pub fn execute(
deps: DepsMut<'_>,
env: Env,
_env: Env,
info: MessageInfo,
msg: ExecuteMsg,
) -> Result<Response, ContractError> {
match msg {
ExecuteMsg::UpdateLockedPledgeCap { amount } => {
try_update_locked_pledge_cap(amount, info, deps)
}
ExecuteMsg::TrackReward { amount, address } => {
try_track_reward(deps, info, amount, &address)
}
ExecuteMsg::ClaimOperatorReward {} => try_claim_operator_reward(deps, info),
ExecuteMsg::ClaimDelegatorReward { mix_identity } => {
try_claim_delegator_reward(deps, info, mix_identity)
}
ExecuteMsg::CompoundDelegatorReward { mix_identity } => {
try_compound_delegator_reward(mix_identity, info, deps)
}
ExecuteMsg::CompoundOperatorReward {} => try_compound_operator_reward(info, deps),
ExecuteMsg::UpdateMixnodeConfig {
profit_margin_percent,
} => try_update_mixnode_config(profit_margin_percent, info, deps),
ExecuteMsg::UpdateMixnetAddress { address } => {
try_update_mixnet_address(address, info, deps)
}
ExecuteMsg::DelegateToMixnode {
mix_identity,
amount,
} => try_delegate_to_mixnode(mix_identity, amount, info, env, deps),
ExecuteMsg::UndelegateFromMixnode { mix_identity } => {
try_undelegate_from_mixnode(mix_identity, info, deps)
}
ExecuteMsg::CreateAccount {
owner_address,
staking_address,
vesting_spec,
} => try_create_periodic_vesting_account(
&owner_address,
staking_address,
vesting_spec,
info,
env,
deps,
),
ExecuteMsg::WithdrawVestedCoins { amount } => {
try_withdraw_vested_coins(amount, env, info, deps)
}
ExecuteMsg::AuthorisedUpdateToV2 {
owner,
node_identity,
mix_id,
} => update_delegation_to_v2(deps, info, owner, node_identity, mix_id),
ExecuteMsg::TrackUndelegation {
owner,
mix_identity,
amount,
} => try_track_undelegation(&owner, mix_identity, amount, info, deps),
ExecuteMsg::BondMixnode {
mix_node,
owner_signature,
amount,
} => try_bond_mixnode(mix_node, owner_signature, amount, info, env, deps),
ExecuteMsg::UnbondMixnode {} => try_unbond_mixnode(info, deps),
ExecuteMsg::TrackUnbondMixnode { owner, amount } => {
try_track_unbond_mixnode(&owner, amount, info, deps)
}
ExecuteMsg::BondGateway {
gateway,
owner_signature,
amount,
} => try_bond_gateway(gateway, owner_signature, amount, info, env, deps),
ExecuteMsg::UnbondGateway {} => try_unbond_gateway(info, deps),
ExecuteMsg::TrackUnbondGateway { owner, amount } => {
try_track_unbond_gateway(&owner, amount, info, deps)
}
ExecuteMsg::TransferOwnership { to_address } => {
try_transfer_ownership(to_address, info, deps)
}
ExecuteMsg::UpdateStakingAddress { to_address } => {
try_update_staking_address(to_address, info, deps)
}
ExecuteMsg::MigrateHeightsToTimestamps {
account_id,
mix_identity,
height_timestamp_map,
} => try_migrate_heights_to_timestamps(
account_id,
mix_identity,
height_timestamp_map,
info,
deps,
),
_ => Err(ContractError::MaintenanceMode),
// ExecuteMsg::UpdateLockedPledgeCap { amount } => {
// try_update_locked_pledge_cap(amount, info, deps)
// }
// ExecuteMsg::TrackReward { amount, address } => {
// try_track_reward(deps, info, amount, &address)
// }
// ExecuteMsg::ClaimOperatorReward {} => try_claim_operator_reward(deps, info),
// ExecuteMsg::ClaimDelegatorReward { mix_identity } => {
// try_claim_delegator_reward(deps, info, mix_identity)
// }
// ExecuteMsg::CompoundDelegatorReward { mix_identity } => {
// try_compound_delegator_reward(mix_identity, info, deps)
// }
// ExecuteMsg::CompoundOperatorReward {} => try_compound_operator_reward(info, deps),
// ExecuteMsg::UpdateMixnodeConfig {
// profit_margin_percent,
// } => try_update_mixnode_config(profit_margin_percent, info, deps),
// ExecuteMsg::UpdateMixnetAddress { address } => {
// try_update_mixnet_address(address, info, deps)
// }
// ExecuteMsg::DelegateToMixnode {
// mix_identity,
// amount,
// } => try_delegate_to_mixnode(mix_identity, amount, info, env, deps),
// ExecuteMsg::UndelegateFromMixnode { mix_identity } => {
// try_undelegate_from_mixnode(mix_identity, info, deps)
// }
// ExecuteMsg::CreateAccount {
// owner_address,
// staking_address,
// vesting_spec,
// } => try_create_periodic_vesting_account(
// &owner_address,
// staking_address,
// vesting_spec,
// info,
// env,
// deps,
// ),
// ExecuteMsg::WithdrawVestedCoins { amount } => {
// try_withdraw_vested_coins(amount, env, info, deps)
// }
//
// ExecuteMsg::BondMixnode {
// mix_node,
// owner_signature,
// amount,
// } => try_bond_mixnode(mix_node, owner_signature, amount, info, env, deps),
// ExecuteMsg::UnbondMixnode {} => try_unbond_mixnode(info, deps),
// ExecuteMsg::TrackUnbondMixnode { owner, amount } => {
// try_track_unbond_mixnode(&owner, amount, info, deps)
// }
// ExecuteMsg::BondGateway {
// gateway,
// owner_signature,
// amount,
// } => try_bond_gateway(gateway, owner_signature, amount, info, env, deps),
// ExecuteMsg::UnbondGateway {} => try_unbond_gateway(info, deps),
// ExecuteMsg::TrackUnbondGateway { owner, amount } => {
// try_track_unbond_gateway(&owner, amount, info, deps)
// }
// ExecuteMsg::TransferOwnership { to_address } => {
// try_transfer_ownership(to_address, info, deps)
// }
// ExecuteMsg::UpdateStakingAddress { to_address } => {
// try_update_staking_address(to_address, info, deps)
// }
}
}
@@ -250,30 +276,6 @@ fn try_update_staking_address(
}
}
pub fn try_migrate_heights_to_timestamps(
account_id: u32,
mix_identity: String,
height_timestamp_map: Vec<(u64, u64)>,
info: MessageInfo,
deps: DepsMut<'_>,
) -> Result<Response, ContractError> {
if info.sender != ADMIN.load(deps.storage)? {
return Err(ContractError::NotAdmin(info.sender.as_str().to_string()));
}
for (height, timestamp) in height_timestamp_map {
let amount = DELEGATIONS.load(deps.storage, (account_id, mix_identity.clone(), height))?;
remove_delegation((account_id, mix_identity.clone(), height), deps.storage)?;
save_delegation(
(account_id, mix_identity.clone(), timestamp),
amount,
deps.storage,
)?;
}
Ok(Response::default())
}
// Owner or staking
pub fn try_bond_gateway(
gateway: Gateway,
@@ -684,20 +686,21 @@ pub fn try_get_delegation_times(
vesting_account_address: &str,
mix_identity: String,
) -> Result<DelegationTimesResponse, ContractError> {
let owner = deps.api.addr_validate(vesting_account_address)?;
let account = account_from_address(vesting_account_address, deps.storage, deps.api)?;
let delegation_timestamps = DELEGATIONS
.prefix((account.storage_key(), mix_identity.clone()))
.keys(deps.storage, None, None, Order::Ascending)
.collect::<StdResult<Vec<_>>>()?;
Ok(DelegationTimesResponse {
owner,
account_id: account.storage_key(),
mix_identity,
delegation_timestamps,
})
Err(ContractError::MaintenanceMode)
// let owner = deps.api.addr_validate(vesting_account_address)?;
// let account = account_from_address(vesting_account_address, deps.storage, deps.api)?;
//
// let delegation_timestamps = DELEGATIONS
// .prefix((account.storage_key(), mix_identity.clone()))
// .keys(deps.storage, None, None, Order::Ascending)
// .collect::<StdResult<Vec<_>>>()?;
//
// Ok(DelegationTimesResponse {
// owner,
// account_id: account.storage_key(),
// mix_identity,
// delegation_timestamps,
// })
}
pub fn try_get_all_delegations(
@@ -705,35 +708,36 @@ pub fn try_get_all_delegations(
start_after: Option<(u32, IdentityKey, BlockTimestampSecs)>,
limit: Option<u32>,
) -> Result<AllDelegationsResponse, ContractError> {
let limit = limit.unwrap_or(100).min(200) as usize;
let start = start_after.map(Bound::exclusive);
let delegations = DELEGATIONS
.range(deps.storage, start, None, Order::Ascending)
.map(|kv| {
kv.map(
|((account_id, mix_identity, block_timestamp), amount)| VestingDelegation {
account_id,
mix_identity,
block_timestamp,
amount,
},
)
})
.collect::<StdResult<Vec<_>>>()?;
let start_next_after = if delegations.len() < limit {
None
} else {
delegations
.last()
.map(|delegation| delegation.storage_key())
};
Ok(AllDelegationsResponse {
delegations,
start_next_after,
})
Err(ContractError::MaintenanceMode)
// let limit = limit.unwrap_or(100).min(200) as usize;
//
// let start = start_after.map(Bound::exclusive);
// let delegations = DELEGATIONS
// .range(deps.storage, start, None, Order::Ascending)
// .map(|kv| {
// kv.map(
// |((account_id, mix_identity, block_timestamp), amount)| VestingDelegation {
// account_id,
// mix_identity,
// block_timestamp,
// amount,
// },
// )
// })
// .collect::<StdResult<Vec<_>>>()?;
//
// let start_next_after = if delegations.len() < limit {
// None
// } else {
// delegations
// .last()
// .map(|delegation| delegation.storage_key())
// };
//
// Ok(AllDelegationsResponse {
// delegations,
// start_next_after,
// })
}
fn validate_funds(funds: &[Coin], mix_denom: String) -> Result<Coin, ContractError> {
+3
View File
@@ -48,4 +48,7 @@ pub enum ContractError {
MinVestingFunds { sent: u128, need: u128 },
#[error("VESTING ({}): Maximum amount of locked coins has already been pledged: {current}, cap is {cap}", line!())]
LockedPledgeCapReached { current: Uint128, cap: Uint128 },
#[error("Contract is currently set to the maintenance mode - all transactions are temporarily disabled")]
MaintenanceMode,
}
+11 -6
View File
@@ -6,6 +6,7 @@ use mixnet_contract_common::IdentityKey;
use vesting_contract_common::PledgeData;
pub(crate) type BlockTimestampSecs = u64;
pub(crate) type NodeId = u32;
pub const KEY: Item<'_, u32> = Item::new("key");
const ACCOUNTS: Map<'_, String, Account> = Map::new("acc");
@@ -14,7 +15,9 @@ const BALANCES: Map<'_, u32, Uint128> = Map::new("blc");
const WITHDRAWNS: Map<'_, u32, Uint128> = Map::new("wthd");
const BOND_PLEDGES: Map<'_, u32, PledgeData> = Map::new("bnd");
const GATEWAY_PLEDGES: Map<'_, u32, PledgeData> = Map::new("gtw");
pub const DELEGATIONS: Map<'_, (u32, IdentityKey, BlockTimestampSecs), Uint128> = Map::new("dlg");
pub const OLD_DELEGATIONS: Map<'_, (u32, IdentityKey, BlockTimestampSecs), Uint128> =
Map::new("dlg");
pub const DELEGATIONS: Map<'_, (u32, NodeId, BlockTimestampSecs), Uint128> = Map::new("dlg_v2");
pub const ADMIN: Item<'_, String> = Item::new("adm");
pub const MIXNET_CONTRACT_ADDRESS: Item<'_, String> = Item::new("mix");
pub const MIX_DENOM: Item<'_, String> = Item::new("den");
@@ -30,8 +33,9 @@ pub fn update_locked_pledge_cap(
amount: Uint128,
storage: &mut dyn Storage,
) -> Result<(), ContractError> {
LOCKED_PLEDGE_CAP.save(storage, &amount)?;
Ok(())
Err(ContractError::MaintenanceMode)
// LOCKED_PLEDGE_CAP.save(storage, &amount)?;
// Ok(())
}
pub fn save_delegation(
@@ -39,15 +43,16 @@ pub fn save_delegation(
amount: Uint128,
storage: &mut dyn Storage,
) -> Result<(), ContractError> {
DELEGATIONS.save(storage, key, &amount)?;
Ok(())
Err(ContractError::MaintenanceMode)
// DELEGATIONS.save(storage, key, &amount)?;
// Ok(())
}
pub fn remove_delegation(
key: (u32, IdentityKey, BlockTimestampSecs),
storage: &mut dyn Storage,
) -> Result<(), ContractError> {
DELEGATIONS.remove(storage, key);
OLD_DELEGATIONS.remove(storage, key);
Ok(())
}
+23 -17
View File
@@ -3,7 +3,7 @@ use crate::errors::ContractError;
use crate::storage::{
load_balance, load_bond_pledge, load_gateway_pledge, load_withdrawn, remove_bond_pledge,
remove_delegation, remove_gateway_pledge, save_account, save_balance, save_bond_pledge,
save_gateway_pledge, save_withdrawn, BlockTimestampSecs, DELEGATIONS, KEY,
save_gateway_pledge, save_withdrawn, BlockTimestampSecs, DELEGATIONS, KEY, OLD_DELEGATIONS,
};
use cosmwasm_std::{Addr, Coin, Order, Storage, Timestamp, Uint128};
use cw_storage_plus::Bound;
@@ -198,11 +198,13 @@ impl Account {
}
pub fn any_delegation_for_mix(&self, mix: &str, storage: &dyn Storage) -> bool {
DELEGATIONS
.prefix((self.storage_key(), mix.to_string()))
.range(storage, None, None, Order::Ascending)
.next()
.is_some()
false
//
// DELEGATIONS
// .prefix((self.storage_key(), mix.to_string()))
// .range(storage, None, None, Order::Ascending)
// .next()
// .is_some()
}
pub fn remove_delegations_for_mix(
@@ -217,7 +219,7 @@ impl Account {
// TODO: Test this
loop {
block_heights.extend(
DELEGATIONS
OLD_DELEGATIONS
.prefix((self.storage_key(), mix.to_string()))
.keys(storage, start_after, None, Order::Ascending)
.take(limit)
@@ -247,19 +249,23 @@ impl Account {
mix: IdentityKey,
storage: &dyn Storage,
) -> Result<Uint128, ContractError> {
Ok(DELEGATIONS
.prefix((self.storage_key(), mix))
.range(storage, None, None, Order::Ascending)
.filter_map(|x| x.ok())
.fold(Uint128::zero(), |acc, (_key, val)| acc + val))
Err(ContractError::MaintenanceMode)
// Ok(DELEGATIONS
// .prefix((self.storage_key(), mix))
// .range(storage, None, None, Order::Ascending)
// .filter_map(|x| x.ok())
// .fold(Uint128::zero(), |acc, (_key, val)| acc + val))
}
pub fn total_delegations(&self, storage: &dyn Storage) -> Result<Uint128, ContractError> {
Ok(DELEGATIONS
.sub_prefix(self.storage_key())
.range(storage, None, None, Order::Ascending)
.filter_map(|x| x.ok())
.fold(Uint128::zero(), |acc, (_key, val)| acc + val))
Err(ContractError::MaintenanceMode)
// Ok(DELEGATIONS
// .sub_prefix(self.storage_key())
// .range(storage, None, None, Order::Ascending)
// .filter_map(|x| x.ok())
// .fold(Uint128::zero(), |acc, (_key, val)| acc + val))
}
pub fn total_delegations_at_timestamp(