Initial mixnet v1->v2 migration code
This commit is contained in:
Generated
+2
-2
@@ -4993,9 +4993,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.83"
|
||||
version = "1.0.85"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "38dd04e3c8279e75b31ef29dbdceebfe5ad89f4d0937213c53f7d49d01b3d5a7"
|
||||
checksum = "e55a28e3aaef9d5ce0506d0a14dbba8054ddc7e499ef522dd8b26859ec9d4a44"
|
||||
dependencies = [
|
||||
"itoa 1.0.1",
|
||||
"ryu",
|
||||
|
||||
@@ -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};
|
||||
|
||||
@@ -213,17 +214,121 @@ 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<u64>,
|
||||
},
|
||||
|
||||
#[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>,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
|
||||
pub enum SpecialVestingMigrateExecuteMsg {
|
||||
UpdateDelegation {
|
||||
owner: String,
|
||||
node_identity: String,
|
||||
mix_id: u64,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
|
||||
pub enum SpecialV2ExecuteMsg {
|
||||
ToBeNamedSaveMixnode {
|
||||
#[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")]
|
||||
proxy: Option<Addr>,
|
||||
},
|
||||
ToBeNamedSaveDelegation {
|
||||
#[serde(rename = "a1")]
|
||||
owner: Addr,
|
||||
|
||||
#[serde(rename = "a2")]
|
||||
mix_id: u64,
|
||||
|
||||
#[serde(rename = "a3")]
|
||||
amount: Coin,
|
||||
|
||||
#[serde(rename = "a4")]
|
||||
block_height: u64,
|
||||
|
||||
#[serde(rename = "a5")]
|
||||
proxy: Option<Addr>,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub struct MigrateMsg {
|
||||
pub mixnet_denom: String,
|
||||
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)]
|
||||
|
||||
@@ -119,6 +119,12 @@ pub enum ExecuteMsg {
|
||||
UpdateLockedPledgeCap {
|
||||
amount: Uint128,
|
||||
},
|
||||
|
||||
AuthorisedUpdateToV2 {
|
||||
owner: String,
|
||||
node_identity: IdentityKey,
|
||||
mix_id: u64,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
|
||||
|
||||
+215
-220
@@ -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,18 +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::migrate_config_from_env;
|
||||
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,
|
||||
@@ -114,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,
|
||||
@@ -127,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,
|
||||
// ),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -509,17 +514,7 @@ fn remove_malicious_node(
|
||||
|
||||
#[entry_point]
|
||||
pub fn migrate(deps: DepsMut<'_>, env: Env, msg: MigrateMsg) -> Result<Response, ContractError> {
|
||||
migrate_config_from_env(deps.storage, &msg)?;
|
||||
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)]
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
|
||||
@@ -1,37 +1,256 @@
|
||||
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use cosmwasm_std::{Addr, Response, Storage};
|
||||
use cw_storage_plus::Item;
|
||||
use mixnet_contract_common::{ContractStateParams, MigrateMsg};
|
||||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::delegations::queries::query_mixnode_delegation;
|
||||
use crate::delegations::storage::delegations;
|
||||
use crate::error::ContractError;
|
||||
use crate::mixnet_contract_settings::models::ContractState;
|
||||
use crate::mixnet_contract_settings::storage::CONTRACT_STATE;
|
||||
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;
|
||||
|
||||
pub fn migrate_config_from_env(
|
||||
storage: &mut dyn Storage,
|
||||
msg: &MigrateMsg,
|
||||
) -> Result<Response, ContractError> {
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
|
||||
pub struct OldContractState {
|
||||
pub owner: Addr,
|
||||
pub rewarding_validator_address: Addr,
|
||||
pub params: ContractStateParams,
|
||||
const MIGRATED_MIXNODES: Map<IdentityKey, u8> = Map::new("migrated-mixnodes");
|
||||
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);
|
||||
}
|
||||
const OLD_CONTRACT_STATE: Item<'_, OldContractState> = Item::new("config");
|
||||
MIGRATED_MIXNODES.save(deps.storage, node_identity.clone(), &1u8)?;
|
||||
|
||||
let old_state = OLD_CONTRACT_STATE.load(storage)?;
|
||||
let new_state = ContractState {
|
||||
owner: old_state.owner,
|
||||
mix_denom: msg.mixnet_denom.clone(),
|
||||
rewarding_validator_address: old_state.rewarding_validator_address,
|
||||
params: old_state.params,
|
||||
let bond = mixnodes()
|
||||
.load(deps.storage, &node_identity)
|
||||
.expect("failed to read mixnode bond");
|
||||
|
||||
let pledge = bond.pledge_amount.clone();
|
||||
let v2_message = SpecialV2ExecuteMsg::ToBeNamedSaveMixnode {
|
||||
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,
|
||||
proxy: bond.proxy,
|
||||
};
|
||||
|
||||
CONTRACT_STATE.save(storage, &new_state)?;
|
||||
|
||||
Ok(Default::default())
|
||||
// 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 is_proxy_vesting(proxy: Option<&Addr>, vesting_contract: &str) -> bool {
|
||||
if let Some(proxy) = proxy {
|
||||
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<u64>,
|
||||
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::ToBeNamedSaveDelegation {
|
||||
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 {
|
||||
let mut to_address = delegation.owner.to_string();
|
||||
let mut make_bank_msg = true;
|
||||
// if the specified proxy matches the vesting contract address -> treat it as "proper" undelegation
|
||||
// and send tokens back there
|
||||
if let Some(proxy) = delegation.proxy {
|
||||
to_address = proxy.to_string();
|
||||
if proxy == vesting_contract {
|
||||
make_bank_msg = false;
|
||||
let vesting_track = VestingContractExecuteMsg::TrackUndelegation {
|
||||
owner: delegation.owner.to_string(),
|
||||
mix_identity: delegation.node_identity,
|
||||
amount: delegation.amount.clone(),
|
||||
};
|
||||
let wasm_msg = wasm_execute(
|
||||
vesting_contract,
|
||||
&vesting_track,
|
||||
vec![delegation.amount.clone()],
|
||||
)?;
|
||||
response.messages.push(SubMsg::new(wasm_msg));
|
||||
}
|
||||
}
|
||||
|
||||
// otherwise just send tokens back to the user / different proxy
|
||||
if make_bank_msg {
|
||||
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_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::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)?,
|
||||
}
|
||||
}
|
||||
|
||||
Ok(response)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user