Feature/adjusting epoch events (#1696)
* Added (not yet using) source height for pending events * Fixed existing unit tests * Emitting source height for resolved pending events * Removed unused attribute keys * Emitting initial total unit reward at time of delegation * Updated ts types * regenerated corresponding typescript types * missed changes * Piggybacking on breaking change to remove serde aliases
This commit is contained in:
committed by
GitHub
parent
fc44f2fe1c
commit
f1624e658e
@@ -9,7 +9,7 @@ use crate::utils::{pretty_cosmwasm_coin, show_error_passthrough};
|
||||
|
||||
use comfy_table::Table;
|
||||
use cosmwasm_std::Addr;
|
||||
use mixnet_contract_common::{Delegation, PendingEpochEvent, PendingEpochEventData};
|
||||
use mixnet_contract_common::{Delegation, PendingEpochEvent, PendingEpochEventKind};
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct Args {}
|
||||
@@ -90,8 +90,8 @@ async fn print_delegation_events(
|
||||
]);
|
||||
|
||||
for event in events {
|
||||
match event.event {
|
||||
PendingEpochEventData::Delegate {
|
||||
match event.event.kind {
|
||||
PendingEpochEventKind::Delegate {
|
||||
owner,
|
||||
mix_id,
|
||||
amount,
|
||||
@@ -107,7 +107,7 @@ async fn print_delegation_events(
|
||||
]);
|
||||
}
|
||||
}
|
||||
PendingEpochEventData::Undelegate {
|
||||
PendingEpochEventKind::Undelegate {
|
||||
owner,
|
||||
mix_id,
|
||||
proxy,
|
||||
|
||||
@@ -34,13 +34,11 @@ pub struct Delegation {
|
||||
pub owner: Addr,
|
||||
|
||||
/// Id of the MixNode that this delegation was performed against.
|
||||
#[serde(alias = "node_id")]
|
||||
pub mix_id: MixId,
|
||||
|
||||
// Note to UI/UX devs: there's absolutely no point in displaying this value to the users,
|
||||
// it would serve them no purpose. It's only used for calculating rewards
|
||||
/// Value of the "unit delegation" associated with the mixnode at the time of delegation.
|
||||
#[serde(alias = "crr")]
|
||||
pub cumulative_reward_ratio: Decimal,
|
||||
|
||||
/// Original delegation amount. Note that it is never mutated as delegation accumulates rewards.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
use crate::mixnode::{MixNodeConfigUpdate, MixNodeCostParams};
|
||||
use crate::reward_params::{IntervalRewardParams, IntervalRewardingParamsUpdate};
|
||||
use crate::rewarding::RewardDistribution;
|
||||
use crate::{ContractStateParams, IdentityKeyRef, Interval, Layer, MixId};
|
||||
use crate::{BlockHeight, ContractStateParams, IdentityKeyRef, Interval, Layer, MixId};
|
||||
pub use contracts_common::events::*;
|
||||
use cosmwasm_std::{Addr, Coin, Decimal, Event};
|
||||
|
||||
@@ -96,7 +96,7 @@ pub const PROXY_KEY: &str = "proxy";
|
||||
// delegation/undelegation
|
||||
pub const DELEGATOR_KEY: &str = "delegator";
|
||||
pub const DELEGATION_TARGET_KEY: &str = "delegation_target";
|
||||
pub const DELEGATION_HEIGHT_KEY: &str = "delegation_latest_block_height";
|
||||
pub const UNIT_REWARD_KEY: &str = "unit_reward";
|
||||
|
||||
// bonding/unbonding
|
||||
pub const MIX_ID_KEY: &str = "mix_id";
|
||||
@@ -120,52 +120,45 @@ pub const UPDATED_MIXNODE_COST_PARAMS_KEY: &str = "updated_mixnode_cost_params";
|
||||
|
||||
// rewarding
|
||||
pub const INTERVAL_KEY: &str = "interval_details";
|
||||
pub const TOTAL_MIXNODE_REWARD_KEY: &str = "total_node_reward";
|
||||
pub const TOTAL_PLEDGE_KEY: &str = "pledge";
|
||||
pub const TOTAL_DELEGATIONS_KEY: &str = "delegated";
|
||||
pub const OPERATOR_REWARD_KEY: &str = "operator_reward";
|
||||
pub const DELEGATES_REWARD_KEY: &str = "delegates_reward";
|
||||
pub const APPROXIMATE_TIME_LEFT_SECS_KEY: &str = "approximate_time_left_secs";
|
||||
pub const INTERVAL_REWARDING_PARAMS_UPDATE_KEY: &str = "interval_rewarding_params_update";
|
||||
pub const UPDATED_INTERVAL_REWARDING_PARAMS_KEY: &str = "updated_interval_rewarding_params";
|
||||
pub const PRIOR_DELEGATES_KEY: &str = "prior_delegates";
|
||||
pub const PRIOR_UNIT_REWARD: &str = "prior_unit_reward";
|
||||
pub const PRIOR_UNIT_REWARD_KEY: &str = "prior_unit_reward";
|
||||
|
||||
pub const DISTRIBUTED_DELEGATION_REWARDS_KEY: &str = "distributed_delegation_rewards";
|
||||
pub const FURTHER_DELEGATIONS_TO_REWARD_KEY: &str = "further_delegations";
|
||||
pub const NO_REWARD_REASON_KEY: &str = "no_reward_reason";
|
||||
pub const BOND_NOT_FOUND_VALUE: &str = "bond_not_found";
|
||||
pub const BOND_TOO_FRESH_VALUE: &str = "bond_too_fresh";
|
||||
pub const ZERO_PERFORMANCE_VALUE: &str = "zero_performance";
|
||||
|
||||
// rewarded set update
|
||||
pub const ACTIVE_SET_SIZE_KEY: &str = "active_set_size";
|
||||
pub const REWARDED_SET_SIZE_KEY: &str = "rewarded_set_size";
|
||||
pub const NODES_IN_REWARDED_SET_KEY: &str = "nodes_in_rewarded_set";
|
||||
pub const CURRENT_INTERVAL_ID_KEY: &str = "current_interval";
|
||||
|
||||
pub const NEW_CURRENT_INTERVAL_KEY: &str = "new_current_interval";
|
||||
pub const NEW_CURRENT_EPOCH_KEY: &str = "new_current_epoch";
|
||||
pub const BLOCK_HEIGHT_KEY: &str = "block_height";
|
||||
pub const RECONCILIATION_ERROR_EVENT: &str = "reconciliation_error";
|
||||
|
||||
// interval
|
||||
pub const EVENTS_EXECUTED_KEY: &str = "number_of_events_executed";
|
||||
pub const EVENT_CREATION_HEIGHT_KEY: &str = "created_at";
|
||||
pub const REWARDED_SET_NODES_KEY: &str = "rewarded_set_nodes";
|
||||
pub const NEW_EPOCHS_DURATION_SECS_KEY: &str = "new_epoch_durations_secs";
|
||||
pub const NEW_EPOCHS_IN_INTERVAL: &str = "new_epochs_in_interval";
|
||||
|
||||
pub fn new_delegation_event(
|
||||
created_at: BlockHeight,
|
||||
delegator: &Addr,
|
||||
proxy: &Option<Addr>,
|
||||
amount: &Coin,
|
||||
mix_id: MixId,
|
||||
unit_reward: Decimal,
|
||||
) -> Event {
|
||||
Event::new(MixnetEventType::Delegation)
|
||||
.add_attribute(EVENT_CREATION_HEIGHT_KEY, created_at.to_string())
|
||||
.add_attribute(DELEGATOR_KEY, delegator)
|
||||
.add_optional_attribute(PROXY_KEY, proxy.as_ref())
|
||||
.add_attribute(AMOUNT_KEY, amount.to_string())
|
||||
.add_attribute(DELEGATION_TARGET_KEY, mix_id.to_string())
|
||||
.add_attribute(UNIT_REWARD_KEY, unit_reward.to_string())
|
||||
}
|
||||
|
||||
pub fn new_delegation_on_unbonded_node_event(
|
||||
@@ -218,8 +211,9 @@ pub fn new_withdraw_delegator_reward_event(
|
||||
.add_attribute(DELEGATION_TARGET_KEY, mix_id.to_string())
|
||||
}
|
||||
|
||||
pub fn new_active_set_update_event(new_size: u32) -> Event {
|
||||
pub fn new_active_set_update_event(created_at: BlockHeight, new_size: u32) -> Event {
|
||||
Event::new(MixnetEventType::ActiveSetUpdate)
|
||||
.add_attribute(EVENT_CREATION_HEIGHT_KEY, created_at.to_string())
|
||||
.add_attribute(ACTIVE_SET_SIZE_KEY, new_size.to_string())
|
||||
}
|
||||
|
||||
@@ -236,10 +230,13 @@ pub fn new_pending_active_set_update_event(
|
||||
}
|
||||
|
||||
pub fn new_rewarding_params_update_event(
|
||||
created_at: BlockHeight,
|
||||
|
||||
update: IntervalRewardingParamsUpdate,
|
||||
updated: IntervalRewardParams,
|
||||
) -> Event {
|
||||
Event::new(MixnetEventType::IntervalRewardingParamsUpdate)
|
||||
.add_attribute(EVENT_CREATION_HEIGHT_KEY, created_at.to_string())
|
||||
.add_attribute(
|
||||
INTERVAL_REWARDING_PARAMS_UPDATE_KEY,
|
||||
update.to_inline_json(),
|
||||
@@ -265,8 +262,14 @@ pub fn new_pending_rewarding_params_update_event(
|
||||
)
|
||||
}
|
||||
|
||||
pub fn new_undelegation_event(delegator: &Addr, proxy: &Option<Addr>, mix_id: MixId) -> Event {
|
||||
pub fn new_undelegation_event(
|
||||
created_at: BlockHeight,
|
||||
delegator: &Addr,
|
||||
proxy: &Option<Addr>,
|
||||
mix_id: MixId,
|
||||
) -> Event {
|
||||
Event::new(MixnetEventType::Undelegation)
|
||||
.add_attribute(EVENT_CREATION_HEIGHT_KEY, created_at.to_string())
|
||||
.add_attribute(DELEGATOR_KEY, delegator)
|
||||
.add_optional_attribute(PROXY_KEY, proxy.as_ref())
|
||||
.add_attribute(MIX_ID_KEY, mix_id.to_string())
|
||||
@@ -327,8 +330,10 @@ pub fn new_mixnode_bonding_event(
|
||||
.add_attribute(AMOUNT_KEY, amount.to_string())
|
||||
}
|
||||
|
||||
pub fn new_mixnode_unbonding_event(mix_id: MixId) -> Event {
|
||||
Event::new(MixnetEventType::MixnodeUnbonding).add_attribute(MIX_ID_KEY, mix_id.to_string())
|
||||
pub fn new_mixnode_unbonding_event(created_at: BlockHeight, mix_id: MixId) -> Event {
|
||||
Event::new(MixnetEventType::MixnodeUnbonding)
|
||||
.add_attribute(EVENT_CREATION_HEIGHT_KEY, created_at.to_string())
|
||||
.add_attribute(MIX_ID_KEY, mix_id.to_string())
|
||||
}
|
||||
|
||||
pub fn new_pending_mixnode_unbonding_event(
|
||||
@@ -370,8 +375,13 @@ pub fn new_mixnode_pending_cost_params_update_event(
|
||||
.add_attribute(UPDATED_MIXNODE_COST_PARAMS_KEY, new_costs.to_inline_json())
|
||||
}
|
||||
|
||||
pub fn new_mixnode_cost_params_update_event(mix_id: MixId, new_costs: &MixNodeCostParams) -> Event {
|
||||
pub fn new_mixnode_cost_params_update_event(
|
||||
created_at: BlockHeight,
|
||||
mix_id: MixId,
|
||||
new_costs: &MixNodeCostParams,
|
||||
) -> Event {
|
||||
Event::new(MixnetEventType::MixnodeCostParamsUpdate)
|
||||
.add_attribute(EVENT_CREATION_HEIGHT_KEY, created_at.to_string())
|
||||
.add_attribute(MIX_ID_KEY, mix_id.to_string())
|
||||
.add_attribute(UPDATED_MIXNODE_COST_PARAMS_KEY, new_costs.to_inline_json())
|
||||
}
|
||||
@@ -461,7 +471,7 @@ pub fn new_mix_rewarding_event(
|
||||
interval.current_epoch_absolute_id().to_string(),
|
||||
)
|
||||
.add_attribute(PRIOR_DELEGATES_KEY, prior_delegates.to_string())
|
||||
.add_attribute(PRIOR_UNIT_REWARD, prior_unit_reward.to_string())
|
||||
.add_attribute(PRIOR_UNIT_REWARD_KEY, prior_unit_reward.to_string())
|
||||
.add_attribute(MIX_ID_KEY, mix_id.to_string())
|
||||
.add_attribute(
|
||||
OPERATOR_REWARD_KEY,
|
||||
@@ -497,11 +507,13 @@ pub fn new_reconcile_pending_events() -> Event {
|
||||
}
|
||||
|
||||
pub fn new_interval_config_update_event(
|
||||
created_at: BlockHeight,
|
||||
epochs_in_interval: u32,
|
||||
epoch_duration_secs: u64,
|
||||
updated_rewarding_params: IntervalRewardParams,
|
||||
) -> Event {
|
||||
Event::new(MixnetEventType::IntervalConfigUpdate)
|
||||
.add_attribute(EVENT_CREATION_HEIGHT_KEY, created_at.to_string())
|
||||
.add_attribute(
|
||||
NEW_EPOCHS_DURATION_SECS_KEY,
|
||||
epoch_duration_secs.to_string(),
|
||||
|
||||
@@ -34,7 +34,8 @@ pub use mixnode::{
|
||||
};
|
||||
pub use msg::*;
|
||||
pub use pending_events::{
|
||||
PendingEpochEvent, PendingEpochEventData, PendingIntervalEvent, PendingIntervalEventData,
|
||||
PendingEpochEvent, PendingEpochEventData, PendingEpochEventKind, PendingIntervalEvent,
|
||||
PendingIntervalEventData, PendingIntervalEventKind,
|
||||
};
|
||||
pub use reward_params::{IntervalRewardParams, IntervalRewardingParamsUpdate, RewardingParams};
|
||||
pub use types::*;
|
||||
|
||||
@@ -78,34 +78,27 @@ impl MixNodeDetails {
|
||||
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)]
|
||||
pub struct MixNodeRewarding {
|
||||
/// Information provided by the operator that influence the cost function.
|
||||
#[serde(alias = "cp")]
|
||||
pub cost_params: MixNodeCostParams,
|
||||
|
||||
/// Total pledge and compounded reward earned by the node operator.
|
||||
#[serde(alias = "op")]
|
||||
pub operator: Decimal,
|
||||
|
||||
/// Total delegation and compounded reward earned by all node delegators.
|
||||
#[serde(alias = "dg")]
|
||||
pub delegates: Decimal,
|
||||
|
||||
/// Cumulative reward earned by the "unit delegation" since the block 0.
|
||||
#[serde(alias = "tur")]
|
||||
pub total_unit_reward: Decimal,
|
||||
|
||||
/// Value of the theoretical "unit delegation" that has delegated to this mixnode at block 0.
|
||||
#[serde(alias = "ud")]
|
||||
pub unit_delegation: Decimal,
|
||||
|
||||
/// Marks the epoch when this node was last rewarded so that we wouldn't accidentally attempt
|
||||
/// to reward it multiple times in the same epoch.
|
||||
#[serde(alias = "le")]
|
||||
pub last_rewarded_epoch: EpochId,
|
||||
|
||||
// technically we don't need that field to determine reward magnitude or anything
|
||||
// but it saves on extra queries to determine if we're removing the final delegation
|
||||
// (so that we could zero the field correctly)
|
||||
#[serde(alias = "uqd")]
|
||||
pub unique_delegations: u32,
|
||||
}
|
||||
|
||||
@@ -428,7 +421,6 @@ impl MixNodeRewarding {
|
||||
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)]
|
||||
pub struct MixNodeBond {
|
||||
/// Unique id assigned to the bonded mixnode.
|
||||
#[serde(alias = "id")]
|
||||
pub mix_id: MixId,
|
||||
|
||||
/// Address of the owner of this mixnode.
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
use crate::mixnode::MixNodeCostParams;
|
||||
use crate::reward_params::IntervalRewardingParamsUpdate;
|
||||
use crate::{EpochEventId, IntervalEventId, MixId};
|
||||
use crate::{BlockHeight, EpochEventId, IntervalEventId, MixId};
|
||||
use cosmwasm_std::{Addr, Coin};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
@@ -14,7 +14,13 @@ pub struct PendingEpochEvent {
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
pub enum PendingEpochEventData {
|
||||
pub struct PendingEpochEventData {
|
||||
pub created_at: BlockHeight,
|
||||
pub kind: PendingEpochEventKind,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
pub enum PendingEpochEventKind {
|
||||
// can't just pass the `Delegation` struct here as it's impossible to determine
|
||||
// `cumulative_reward_ratio` ahead of time
|
||||
Delegate {
|
||||
@@ -36,6 +42,15 @@ pub enum PendingEpochEventData {
|
||||
},
|
||||
}
|
||||
|
||||
impl PendingEpochEventKind {
|
||||
pub fn attach_source_height(self, created_at: BlockHeight) -> PendingEpochEventData {
|
||||
PendingEpochEventData {
|
||||
created_at,
|
||||
kind: self,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<(EpochEventId, PendingEpochEventData)> for PendingEpochEvent {
|
||||
fn from(data: (EpochEventId, PendingEpochEventData)) -> Self {
|
||||
PendingEpochEvent {
|
||||
@@ -52,7 +67,13 @@ pub struct PendingIntervalEvent {
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
pub enum PendingIntervalEventData {
|
||||
pub struct PendingIntervalEventData {
|
||||
pub created_at: BlockHeight,
|
||||
pub kind: PendingIntervalEventKind,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
pub enum PendingIntervalEventKind {
|
||||
ChangeMixCostParams {
|
||||
mix_id: MixId,
|
||||
new_costs: MixNodeCostParams,
|
||||
@@ -67,6 +88,15 @@ pub enum PendingIntervalEventData {
|
||||
},
|
||||
}
|
||||
|
||||
impl PendingIntervalEventKind {
|
||||
pub fn attach_source_height(self, created_at: BlockHeight) -> PendingIntervalEventData {
|
||||
PendingIntervalEventData {
|
||||
created_at,
|
||||
kind: self,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<(IntervalEventId, PendingIntervalEventData)> for PendingIntervalEvent {
|
||||
fn from(data: (IntervalEventId, PendingIntervalEventData)) -> Self {
|
||||
PendingIntervalEvent {
|
||||
|
||||
@@ -20,6 +20,7 @@ pub type SphinxKeyRef<'a> = &'a str;
|
||||
pub type EpochId = u32;
|
||||
pub type IntervalId = u32;
|
||||
pub type MixId = u32;
|
||||
pub type BlockHeight = u64;
|
||||
pub type EpochEventId = u32;
|
||||
pub type IntervalEventId = u32;
|
||||
|
||||
|
||||
@@ -5,11 +5,11 @@ use crate::currency::{DecCoin, RegisteredCoins};
|
||||
use crate::error::TypesError;
|
||||
use crate::mixnode::MixNodeCostParams;
|
||||
use mixnet_contract_common::{
|
||||
EpochEventId, IntervalEventId, IntervalRewardingParamsUpdate, MixId,
|
||||
BlockHeight, EpochEventId, IntervalEventId, IntervalRewardingParamsUpdate, MixId,
|
||||
PendingEpochEvent as MixnetContractPendingEpochEvent,
|
||||
PendingEpochEventData as MixnetContractPendingEpochEventData,
|
||||
PendingEpochEventKind as MixnetContractPendingEpochEventKind,
|
||||
PendingIntervalEvent as MixnetContractPendingIntervalEvent,
|
||||
PendingIntervalEventData as MixnetContractPendingIntervalEventData,
|
||||
PendingIntervalEventKind as MixnetContractPendingIntervalEventKind,
|
||||
};
|
||||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
@@ -22,6 +22,7 @@ use serde::{Deserialize, Serialize};
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq, JsonSchema)]
|
||||
pub struct PendingEpochEvent {
|
||||
pub id: EpochEventId,
|
||||
pub created_at: BlockHeight,
|
||||
pub event: PendingEpochEventData,
|
||||
}
|
||||
|
||||
@@ -32,7 +33,8 @@ impl PendingEpochEvent {
|
||||
) -> Result<Self, TypesError> {
|
||||
Ok(PendingEpochEvent {
|
||||
id: pending_event.id,
|
||||
event: PendingEpochEventData::try_from_mixnet_contract(pending_event.event, reg)?,
|
||||
created_at: pending_event.event.created_at,
|
||||
event: PendingEpochEventData::try_from_mixnet_contract(pending_event.event.kind, reg)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -65,11 +67,11 @@ pub enum PendingEpochEventData {
|
||||
|
||||
impl PendingEpochEventData {
|
||||
pub fn try_from_mixnet_contract(
|
||||
pending_event: MixnetContractPendingEpochEventData,
|
||||
pending_event: MixnetContractPendingEpochEventKind,
|
||||
reg: &RegisteredCoins,
|
||||
) -> Result<Self, TypesError> {
|
||||
match pending_event {
|
||||
MixnetContractPendingEpochEventData::Delegate {
|
||||
MixnetContractPendingEpochEventKind::Delegate {
|
||||
owner,
|
||||
mix_id,
|
||||
amount,
|
||||
@@ -80,7 +82,7 @@ impl PendingEpochEventData {
|
||||
amount: reg.attempt_convert_to_display_dec_coin(amount.into())?,
|
||||
proxy: proxy.map(|p| p.into_string()),
|
||||
}),
|
||||
MixnetContractPendingEpochEventData::Undelegate {
|
||||
MixnetContractPendingEpochEventKind::Undelegate {
|
||||
owner,
|
||||
mix_id,
|
||||
proxy,
|
||||
@@ -89,10 +91,10 @@ impl PendingEpochEventData {
|
||||
mix_id,
|
||||
proxy: proxy.map(|p| p.into_string()),
|
||||
}),
|
||||
MixnetContractPendingEpochEventData::UnbondMixnode { mix_id } => {
|
||||
MixnetContractPendingEpochEventKind::UnbondMixnode { mix_id } => {
|
||||
Ok(PendingEpochEventData::UnbondMixnode { mix_id })
|
||||
}
|
||||
MixnetContractPendingEpochEventData::UpdateActiveSetSize { new_size } => {
|
||||
MixnetContractPendingEpochEventKind::UpdateActiveSetSize { new_size } => {
|
||||
Ok(PendingEpochEventData::UpdateActiveSetSize { new_size })
|
||||
}
|
||||
}
|
||||
@@ -107,6 +109,7 @@ impl PendingEpochEventData {
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq, JsonSchema)]
|
||||
pub struct PendingIntervalEvent {
|
||||
pub id: IntervalEventId,
|
||||
pub created_at: BlockHeight,
|
||||
pub event: PendingIntervalEventData,
|
||||
}
|
||||
|
||||
@@ -117,7 +120,11 @@ impl PendingIntervalEvent {
|
||||
) -> Result<Self, TypesError> {
|
||||
Ok(PendingIntervalEvent {
|
||||
id: pending_event.id,
|
||||
event: PendingIntervalEventData::try_from_mixnet_contract(pending_event.event, reg)?,
|
||||
created_at: pending_event.event.created_at,
|
||||
event: PendingIntervalEventData::try_from_mixnet_contract(
|
||||
pending_event.event.kind,
|
||||
reg,
|
||||
)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -145,11 +152,11 @@ pub enum PendingIntervalEventData {
|
||||
|
||||
impl PendingIntervalEventData {
|
||||
pub fn try_from_mixnet_contract(
|
||||
pending_event: MixnetContractPendingIntervalEventData,
|
||||
pending_event: MixnetContractPendingIntervalEventKind,
|
||||
reg: &RegisteredCoins,
|
||||
) -> Result<Self, TypesError> {
|
||||
match pending_event {
|
||||
MixnetContractPendingIntervalEventData::ChangeMixCostParams { mix_id, new_costs } => {
|
||||
MixnetContractPendingIntervalEventKind::ChangeMixCostParams { mix_id, new_costs } => {
|
||||
Ok(PendingIntervalEventData::ChangeMixCostParams {
|
||||
mix_id,
|
||||
new_costs: MixNodeCostParams::from_mixnet_contract_mixnode_cost_params(
|
||||
@@ -157,10 +164,10 @@ impl PendingIntervalEventData {
|
||||
)?,
|
||||
})
|
||||
}
|
||||
MixnetContractPendingIntervalEventData::UpdateRewardingParams { update } => {
|
||||
MixnetContractPendingIntervalEventKind::UpdateRewardingParams { update } => {
|
||||
Ok(PendingIntervalEventData::UpdateRewardingParams { update })
|
||||
}
|
||||
MixnetContractPendingIntervalEventData::UpdateIntervalConfig {
|
||||
MixnetContractPendingIntervalEventKind::UpdateIntervalConfig {
|
||||
epochs_in_interval,
|
||||
epoch_duration_secs,
|
||||
} => Ok(PendingIntervalEventData::UpdateIntervalConfig {
|
||||
|
||||
@@ -169,17 +169,19 @@ pub fn execute(
|
||||
owner_signature,
|
||||
),
|
||||
ExecuteMsg::UnbondMixnode {} => {
|
||||
crate::mixnodes::transactions::try_remove_mixnode(deps, info)
|
||||
crate::mixnodes::transactions::try_remove_mixnode(deps, env, info)
|
||||
}
|
||||
ExecuteMsg::UnbondMixnodeOnBehalf { owner } => {
|
||||
crate::mixnodes::transactions::try_remove_mixnode_on_behalf(deps, info, owner)
|
||||
crate::mixnodes::transactions::try_remove_mixnode_on_behalf(deps, env, info, owner)
|
||||
}
|
||||
ExecuteMsg::UpdateMixnodeCostParams { new_costs } => {
|
||||
crate::mixnodes::transactions::try_update_mixnode_cost_params(deps, info, new_costs)
|
||||
crate::mixnodes::transactions::try_update_mixnode_cost_params(
|
||||
deps, env, info, new_costs,
|
||||
)
|
||||
}
|
||||
ExecuteMsg::UpdateMixnodeCostParamsOnBehalf { new_costs, owner } => {
|
||||
crate::mixnodes::transactions::try_update_mixnode_cost_params_on_behalf(
|
||||
deps, info, new_costs, owner,
|
||||
deps, env, info, new_costs, owner,
|
||||
)
|
||||
}
|
||||
ExecuteMsg::UpdateMixnodeConfig { new_config } => {
|
||||
@@ -223,19 +225,21 @@ pub fn execute(
|
||||
|
||||
// delegation-related:
|
||||
ExecuteMsg::DelegateToMixnode { mix_id } => {
|
||||
crate::delegations::transactions::try_delegate_to_mixnode(deps, info, mix_id)
|
||||
crate::delegations::transactions::try_delegate_to_mixnode(deps, env, info, mix_id)
|
||||
}
|
||||
ExecuteMsg::DelegateToMixnodeOnBehalf { mix_id, delegate } => {
|
||||
crate::delegations::transactions::try_delegate_to_mixnode_on_behalf(
|
||||
deps, info, mix_id, delegate,
|
||||
deps, env, info, mix_id, delegate,
|
||||
)
|
||||
}
|
||||
ExecuteMsg::UndelegateFromMixnode { mix_id } => {
|
||||
crate::delegations::transactions::try_remove_delegation_from_mixnode(deps, info, mix_id)
|
||||
crate::delegations::transactions::try_remove_delegation_from_mixnode(
|
||||
deps, env, info, mix_id,
|
||||
)
|
||||
}
|
||||
ExecuteMsg::UndelegateFromMixnodeOnBehalf { mix_id, delegate } => {
|
||||
crate::delegations::transactions::try_remove_delegation_from_mixnode_on_behalf(
|
||||
deps, info, mix_id, delegate,
|
||||
deps, env, info, mix_id, delegate,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -453,6 +453,7 @@ mod tests {
|
||||
#[test]
|
||||
fn all_retrieved_delegations_are_from_the_specified_delegator() {
|
||||
let mut test = TestSetup::new();
|
||||
let env = test.env();
|
||||
// it means we have, for example, delegation from "delegator1" towards mix1, mix2, ...., from "delegator2" towards mix1, mix2, ...., etc
|
||||
add_dummy_mixes_with_delegations(&mut test, 50, 100);
|
||||
|
||||
@@ -462,6 +463,7 @@ mod tests {
|
||||
for mix_id in 1..=25 {
|
||||
try_delegate_to_mixnode_on_behalf(
|
||||
test.deps_mut(),
|
||||
env.clone(),
|
||||
mock_info(vesting_contract.as_ref(), &[coin(100_000, TEST_COIN_DENOM)]),
|
||||
mix_id,
|
||||
with_proxy.into(),
|
||||
|
||||
@@ -6,34 +6,37 @@ use crate::interval::storage as interval_storage;
|
||||
use crate::mixnet_contract_settings::storage as mixnet_params_storage;
|
||||
use crate::mixnodes::storage as mixnodes_storage;
|
||||
use crate::support::helpers::validate_delegation_stake;
|
||||
use cosmwasm_std::{Addr, Coin, DepsMut, MessageInfo, Response};
|
||||
use cosmwasm_std::{Addr, Coin, DepsMut, Env, MessageInfo, Response};
|
||||
use mixnet_contract_common::error::MixnetContractError;
|
||||
use mixnet_contract_common::events::{
|
||||
new_pending_delegation_event, new_pending_undelegation_event,
|
||||
};
|
||||
use mixnet_contract_common::pending_events::PendingEpochEventData;
|
||||
use mixnet_contract_common::pending_events::PendingEpochEventKind;
|
||||
use mixnet_contract_common::{Delegation, MixId};
|
||||
|
||||
pub(crate) fn try_delegate_to_mixnode(
|
||||
deps: DepsMut<'_>,
|
||||
env: Env,
|
||||
info: MessageInfo,
|
||||
mix_id: MixId,
|
||||
) -> Result<Response, MixnetContractError> {
|
||||
_try_delegate_to_mixnode(deps, mix_id, info.sender, info.funds, None)
|
||||
_try_delegate_to_mixnode(deps, env, mix_id, info.sender, info.funds, None)
|
||||
}
|
||||
|
||||
pub(crate) fn try_delegate_to_mixnode_on_behalf(
|
||||
deps: DepsMut<'_>,
|
||||
env: Env,
|
||||
info: MessageInfo,
|
||||
mix_id: MixId,
|
||||
delegate: String,
|
||||
) -> Result<Response, MixnetContractError> {
|
||||
let delegate = deps.api.addr_validate(&delegate)?;
|
||||
_try_delegate_to_mixnode(deps, mix_id, delegate, info.funds, Some(info.sender))
|
||||
_try_delegate_to_mixnode(deps, env, mix_id, delegate, info.funds, Some(info.sender))
|
||||
}
|
||||
|
||||
pub(crate) fn _try_delegate_to_mixnode(
|
||||
deps: DepsMut<'_>,
|
||||
env: Env,
|
||||
mix_id: MixId,
|
||||
delegate: Addr,
|
||||
amount: Vec<Coin>,
|
||||
@@ -59,37 +62,40 @@ pub(crate) fn _try_delegate_to_mixnode(
|
||||
// push the event onto the queue and wait for it to be picked up at the end of the epoch
|
||||
let cosmos_event = new_pending_delegation_event(&delegate, &proxy, &delegation, mix_id);
|
||||
|
||||
let epoch_event = PendingEpochEventData::Delegate {
|
||||
let epoch_event = PendingEpochEventKind::Delegate {
|
||||
owner: delegate,
|
||||
mix_id,
|
||||
amount: delegation,
|
||||
proxy,
|
||||
};
|
||||
interval_storage::push_new_epoch_event(deps.storage, &epoch_event)?;
|
||||
interval_storage::push_new_epoch_event(deps.storage, &env, epoch_event)?;
|
||||
|
||||
Ok(Response::new().add_event(cosmos_event))
|
||||
}
|
||||
|
||||
pub(crate) fn try_remove_delegation_from_mixnode(
|
||||
deps: DepsMut<'_>,
|
||||
env: Env,
|
||||
info: MessageInfo,
|
||||
mix_id: MixId,
|
||||
) -> Result<Response, MixnetContractError> {
|
||||
_try_remove_delegation_from_mixnode(deps, mix_id, info.sender, None)
|
||||
_try_remove_delegation_from_mixnode(deps, env, mix_id, info.sender, None)
|
||||
}
|
||||
|
||||
pub(crate) fn try_remove_delegation_from_mixnode_on_behalf(
|
||||
deps: DepsMut<'_>,
|
||||
env: Env,
|
||||
info: MessageInfo,
|
||||
mix_id: MixId,
|
||||
delegate: String,
|
||||
) -> Result<Response, MixnetContractError> {
|
||||
let delegate = deps.api.addr_validate(&delegate)?;
|
||||
_try_remove_delegation_from_mixnode(deps, mix_id, delegate, Some(info.sender))
|
||||
_try_remove_delegation_from_mixnode(deps, env, mix_id, delegate, Some(info.sender))
|
||||
}
|
||||
|
||||
pub(crate) fn _try_remove_delegation_from_mixnode(
|
||||
deps: DepsMut<'_>,
|
||||
env: Env,
|
||||
mix_id: MixId,
|
||||
delegate: Addr,
|
||||
proxy: Option<Addr>,
|
||||
@@ -111,12 +117,12 @@ pub(crate) fn _try_remove_delegation_from_mixnode(
|
||||
// push the event onto the queue and wait for it to be picked up at the end of the epoch
|
||||
let cosmos_event = new_pending_undelegation_event(&delegate, &proxy, mix_id);
|
||||
|
||||
let epoch_event = PendingEpochEventData::Undelegate {
|
||||
let epoch_event = PendingEpochEventKind::Undelegate {
|
||||
owner: delegate,
|
||||
mix_id,
|
||||
proxy,
|
||||
};
|
||||
interval_storage::push_new_epoch_event(deps.storage, &epoch_event)?;
|
||||
interval_storage::push_new_epoch_event(deps.storage, &env, epoch_event)?;
|
||||
|
||||
Ok(Response::new().add_event(cosmos_event))
|
||||
}
|
||||
@@ -138,10 +144,11 @@ mod tests {
|
||||
#[test]
|
||||
fn can_only_be_done_towards_an_existing_mixnode() {
|
||||
let mut test = TestSetup::new();
|
||||
let env = test.env();
|
||||
let owner = "delegator";
|
||||
let sender = mock_info(owner, &[coin(100_000_000, TEST_COIN_DENOM)]);
|
||||
|
||||
let res = try_delegate_to_mixnode(test.deps_mut(), sender, 42);
|
||||
let res = try_delegate_to_mixnode(test.deps_mut(), env, sender, 42);
|
||||
assert_eq!(
|
||||
res,
|
||||
Err(MixnetContractError::MixNodeBondNotFound { mix_id: 42 })
|
||||
@@ -151,17 +158,19 @@ mod tests {
|
||||
#[test]
|
||||
fn must_contain_non_zero_amount_of_coins() {
|
||||
let mut test = TestSetup::new();
|
||||
let env = test.env();
|
||||
|
||||
let owner = "delegator";
|
||||
let mix_id = test.add_dummy_mixnode("mix-owner", None);
|
||||
let sender1 = mock_info(owner, &[coin(0, TEST_COIN_DENOM)]);
|
||||
let sender2 = mock_info(owner, &[]);
|
||||
let sender3 = mock_info(owner, &[coin(1000, "some-weird-coin")]);
|
||||
|
||||
let res = try_delegate_to_mixnode(test.deps_mut(), sender1, mix_id);
|
||||
let res = try_delegate_to_mixnode(test.deps_mut(), env.clone(), sender1, mix_id);
|
||||
assert_eq!(res, Err(MixnetContractError::EmptyDelegation));
|
||||
let res = try_delegate_to_mixnode(test.deps_mut(), sender2, mix_id);
|
||||
let res = try_delegate_to_mixnode(test.deps_mut(), env.clone(), sender2, mix_id);
|
||||
assert_eq!(res, Err(MixnetContractError::EmptyDelegation));
|
||||
let res = try_delegate_to_mixnode(test.deps_mut(), sender3, mix_id);
|
||||
let res = try_delegate_to_mixnode(test.deps_mut(), env, sender3, mix_id);
|
||||
assert_eq!(
|
||||
res,
|
||||
Err(MixnetContractError::WrongDenom {
|
||||
@@ -174,6 +183,8 @@ mod tests {
|
||||
#[test]
|
||||
fn if_applicable_must_contain_at_least_the_minimum_pledge() {
|
||||
let mut test = TestSetup::new();
|
||||
let env = test.env();
|
||||
|
||||
let owner = "delegator";
|
||||
let mix_id = test.add_dummy_mixnode("mix-owner", None);
|
||||
let sender1 = mock_info(owner, &[coin(100_000_000, TEST_COIN_DENOM)]);
|
||||
@@ -188,7 +199,7 @@ mod tests {
|
||||
.save(test.deps_mut().storage, &contract_state)
|
||||
.unwrap();
|
||||
|
||||
let res = try_delegate_to_mixnode(test.deps_mut(), sender1, mix_id);
|
||||
let res = try_delegate_to_mixnode(test.deps_mut(), env.clone(), sender1, mix_id);
|
||||
assert_eq!(
|
||||
res,
|
||||
Err(MixnetContractError::InsufficientDelegation {
|
||||
@@ -197,13 +208,14 @@ mod tests {
|
||||
})
|
||||
);
|
||||
|
||||
let res = try_delegate_to_mixnode(test.deps_mut(), sender2, mix_id);
|
||||
let res = try_delegate_to_mixnode(test.deps_mut(), env, sender2, mix_id);
|
||||
assert!(res.is_ok())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn can_only_be_done_towards_fully_bonded_mixnode() {
|
||||
let mut test = TestSetup::new();
|
||||
let env = test.env();
|
||||
let owner = "delegator";
|
||||
let sender = mock_info(owner, &[coin(100_000_000, TEST_COIN_DENOM)]);
|
||||
|
||||
@@ -226,17 +238,33 @@ mod tests {
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
try_remove_mixnode(test.deps_mut(), mock_info("mix-owner-unbonded", &[])).unwrap();
|
||||
try_remove_mixnode(
|
||||
test.deps_mut(),
|
||||
env.clone(),
|
||||
mock_info("mix-owner-unbonded", &[]),
|
||||
)
|
||||
.unwrap();
|
||||
try_remove_mixnode(
|
||||
test.deps_mut(),
|
||||
env.clone(),
|
||||
mock_info("mix-owner-unbonded-leftover", &[]),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
test.execute_all_pending_events();
|
||||
try_remove_mixnode(test.deps_mut(), mock_info("mix-owner-unbonding", &[])).unwrap();
|
||||
try_remove_mixnode(
|
||||
test.deps_mut(),
|
||||
env.clone(),
|
||||
mock_info("mix-owner-unbonding", &[]),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let res = try_delegate_to_mixnode(test.deps_mut(), sender.clone(), mix_id_unbonding);
|
||||
let res = try_delegate_to_mixnode(
|
||||
test.deps_mut(),
|
||||
env.clone(),
|
||||
sender.clone(),
|
||||
mix_id_unbonding,
|
||||
);
|
||||
assert_eq!(
|
||||
res,
|
||||
Err(MixnetContractError::MixnodeIsUnbonding {
|
||||
@@ -244,7 +272,12 @@ mod tests {
|
||||
})
|
||||
);
|
||||
|
||||
let res = try_delegate_to_mixnode(test.deps_mut(), sender.clone(), mix_id_unbonded);
|
||||
let res = try_delegate_to_mixnode(
|
||||
test.deps_mut(),
|
||||
env.clone(),
|
||||
sender.clone(),
|
||||
mix_id_unbonded,
|
||||
);
|
||||
assert_eq!(
|
||||
res,
|
||||
Err(MixnetContractError::MixNodeBondNotFound {
|
||||
@@ -252,7 +285,8 @@ mod tests {
|
||||
})
|
||||
);
|
||||
|
||||
let res = try_delegate_to_mixnode(test.deps_mut(), sender, mix_id_unbonded_leftover);
|
||||
let res =
|
||||
try_delegate_to_mixnode(test.deps_mut(), env, sender, mix_id_unbonded_leftover);
|
||||
assert_eq!(
|
||||
res,
|
||||
Err(MixnetContractError::MixNodeBondNotFound {
|
||||
@@ -264,22 +298,26 @@ mod tests {
|
||||
#[test]
|
||||
fn can_still_be_done_if_prior_delegation_exists() {
|
||||
let mut test = TestSetup::new();
|
||||
let env = test.env();
|
||||
|
||||
let owner = "delegator";
|
||||
let mix_id = test.add_dummy_mixnode("mix-owner", None);
|
||||
let sender1 = mock_info(owner, &[coin(100_000_000, TEST_COIN_DENOM)]);
|
||||
let sender2 = mock_info(owner, &[coin(50_000_000, TEST_COIN_DENOM)]);
|
||||
|
||||
let res = try_delegate_to_mixnode(test.deps_mut(), sender1, mix_id);
|
||||
let res = try_delegate_to_mixnode(test.deps_mut(), env.clone(), sender1, mix_id);
|
||||
assert!(res.is_ok());
|
||||
|
||||
// still OK
|
||||
let res = try_delegate_to_mixnode(test.deps_mut(), sender2, mix_id);
|
||||
let res = try_delegate_to_mixnode(test.deps_mut(), env, sender2, mix_id);
|
||||
assert!(res.is_ok())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn correctly_pushes_appropriate_epoch_event() {
|
||||
let mut test = TestSetup::new();
|
||||
let env = test.env();
|
||||
|
||||
let owner = "delegator";
|
||||
let mix_id = test.add_dummy_mixnode("mix-owner", None);
|
||||
|
||||
@@ -289,15 +327,15 @@ mod tests {
|
||||
let sender1 = mock_info(owner, &[amount1.clone()]);
|
||||
let sender2 = mock_info(test.vesting_contract().as_str(), &[amount2.clone()]);
|
||||
|
||||
try_delegate_to_mixnode(test.deps_mut(), sender1, mix_id).unwrap();
|
||||
try_delegate_to_mixnode_on_behalf(test.deps_mut(), sender2, mix_id, owner.into())
|
||||
try_delegate_to_mixnode(test.deps_mut(), env.clone(), sender1, mix_id).unwrap();
|
||||
try_delegate_to_mixnode_on_behalf(test.deps_mut(), env, sender2, mix_id, owner.into())
|
||||
.unwrap();
|
||||
|
||||
let events = test.pending_epoch_events();
|
||||
|
||||
assert_eq!(
|
||||
events[0],
|
||||
PendingEpochEventData::Delegate {
|
||||
events[0].kind,
|
||||
PendingEpochEventKind::Delegate {
|
||||
owner: Addr::unchecked(owner),
|
||||
mix_id,
|
||||
amount: amount1,
|
||||
@@ -306,8 +344,8 @@ mod tests {
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
events[1],
|
||||
PendingEpochEventData::Delegate {
|
||||
events[1].kind,
|
||||
PendingEpochEventKind::Delegate {
|
||||
owner: Addr::unchecked(owner),
|
||||
mix_id,
|
||||
amount: amount2,
|
||||
@@ -329,11 +367,12 @@ mod tests {
|
||||
#[test]
|
||||
fn cannot_be_performed_if_delegation_never_existed() {
|
||||
let mut test = TestSetup::new();
|
||||
let env = test.env();
|
||||
let owner = "delegator";
|
||||
let sender = mock_info(owner, &[]);
|
||||
let mix_id = test.add_dummy_mixnode("mix-owner", None);
|
||||
|
||||
let res = try_remove_delegation_from_mixnode(test.deps_mut(), sender, mix_id);
|
||||
let res = try_remove_delegation_from_mixnode(test.deps_mut(), env, sender, mix_id);
|
||||
assert_eq!(
|
||||
res,
|
||||
Err(MixnetContractError::NoMixnodeDelegationFound {
|
||||
@@ -347,14 +386,16 @@ mod tests {
|
||||
#[test]
|
||||
fn cannot_be_performed_if_the_delegation_is_still_pending() {
|
||||
let mut test = TestSetup::new();
|
||||
let env = test.env();
|
||||
|
||||
let owner = "delegator";
|
||||
let mix_id = test.add_dummy_mixnode("mix-owner", None);
|
||||
let sender1 = mock_info(owner, &[coin(100_000_000, TEST_COIN_DENOM)]);
|
||||
let sender2 = mock_info(owner, &[]);
|
||||
|
||||
try_delegate_to_mixnode(test.deps_mut(), sender1, mix_id).unwrap();
|
||||
try_delegate_to_mixnode(test.deps_mut(), env.clone(), sender1, mix_id).unwrap();
|
||||
|
||||
let res = try_remove_delegation_from_mixnode(test.deps_mut(), sender2, mix_id);
|
||||
let res = try_remove_delegation_from_mixnode(test.deps_mut(), env, sender2, mix_id);
|
||||
assert_eq!(
|
||||
res,
|
||||
Err(MixnetContractError::NoMixnodeDelegationFound {
|
||||
@@ -368,6 +409,8 @@ mod tests {
|
||||
#[test]
|
||||
fn as_long_as_delegation_exists_can_always_be_performed() {
|
||||
let mut test = TestSetup::new();
|
||||
let env = test.env();
|
||||
|
||||
let owner = "delegator";
|
||||
let sender = mock_info(owner, &[]);
|
||||
|
||||
@@ -382,19 +425,30 @@ mod tests {
|
||||
|
||||
try_remove_mixnode(
|
||||
test.deps_mut(),
|
||||
env.clone(),
|
||||
mock_info("mix-owner-unbonded-leftover", &[]),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
test.execute_all_pending_events();
|
||||
try_remove_mixnode(test.deps_mut(), mock_info("mix-owner-unbonding", &[])).unwrap();
|
||||
try_remove_mixnode(
|
||||
test.deps_mut(),
|
||||
env.clone(),
|
||||
mock_info("mix-owner-unbonding", &[]),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let res =
|
||||
try_remove_delegation_from_mixnode(test.deps_mut(), sender.clone(), normal_mix_id);
|
||||
let res = try_remove_delegation_from_mixnode(
|
||||
test.deps_mut(),
|
||||
env.clone(),
|
||||
sender.clone(),
|
||||
normal_mix_id,
|
||||
);
|
||||
assert!(res.is_ok());
|
||||
|
||||
let res = try_remove_delegation_from_mixnode(
|
||||
test.deps_mut(),
|
||||
env.clone(),
|
||||
sender.clone(),
|
||||
mix_id_unbonding,
|
||||
);
|
||||
@@ -402,6 +456,7 @@ mod tests {
|
||||
|
||||
let res = try_remove_delegation_from_mixnode(
|
||||
test.deps_mut(),
|
||||
env,
|
||||
sender,
|
||||
mix_id_unbonded_leftover,
|
||||
);
|
||||
|
||||
@@ -274,7 +274,7 @@ pub mod tests {
|
||||
assert_eq!(Err(MixnetContractError::AlreadyOwnsMixnode), result);
|
||||
|
||||
// but after he unbonds it, it's all fine again
|
||||
pending_events::unbond_mixnode(deps.as_mut(), &env, mix_id).unwrap();
|
||||
pending_events::unbond_mixnode(deps.as_mut(), &env, 123, mix_id).unwrap();
|
||||
|
||||
let result = try_add_gateway(deps.as_mut(), env, info, gateway, sig);
|
||||
assert!(result.is_ok());
|
||||
|
||||
@@ -6,11 +6,12 @@ use crate::rewards::storage as rewards_storage;
|
||||
use cosmwasm_std::{Response, Storage};
|
||||
use mixnet_contract_common::error::MixnetContractError;
|
||||
use mixnet_contract_common::events::new_interval_config_update_event;
|
||||
use mixnet_contract_common::Interval;
|
||||
use mixnet_contract_common::{BlockHeight, Interval};
|
||||
use std::time::Duration;
|
||||
|
||||
pub(crate) fn change_interval_config(
|
||||
store: &mut dyn Storage,
|
||||
request_creation: BlockHeight,
|
||||
mut current_interval: Interval,
|
||||
epochs_in_interval: u32,
|
||||
epoch_duration_secs: u64,
|
||||
@@ -25,6 +26,7 @@ pub(crate) fn change_interval_config(
|
||||
storage::save_interval(store, ¤t_interval)?;
|
||||
|
||||
Ok(Response::new().add_event(new_interval_config_update_event(
|
||||
request_creation,
|
||||
epochs_in_interval,
|
||||
epoch_duration_secs,
|
||||
rewarding_params.interval,
|
||||
@@ -50,6 +52,7 @@ mod tests {
|
||||
// if we half the number of epochs, the reward budget should get doubled
|
||||
change_interval_config(
|
||||
&mut deps.storage,
|
||||
123,
|
||||
initial_interval,
|
||||
initial_interval.epochs_in_interval() / 2,
|
||||
initial_interval.epoch_length_secs(),
|
||||
@@ -72,6 +75,7 @@ mod tests {
|
||||
// and similarly when we double number of epochs, the reward budget should get halved
|
||||
change_interval_config(
|
||||
&mut deps.storage,
|
||||
123,
|
||||
initial_interval,
|
||||
initial_interval.epochs_in_interval() * 2,
|
||||
initial_interval.epoch_length_secs(),
|
||||
|
||||
@@ -17,9 +17,12 @@ use mixnet_contract_common::events::{
|
||||
new_rewarding_params_update_event, new_undelegation_event,
|
||||
};
|
||||
use mixnet_contract_common::mixnode::MixNodeCostParams;
|
||||
use mixnet_contract_common::pending_events::{PendingEpochEventData, PendingIntervalEventData};
|
||||
use mixnet_contract_common::pending_events::{
|
||||
PendingEpochEventData, PendingEpochEventKind, PendingIntervalEventData,
|
||||
PendingIntervalEventKind,
|
||||
};
|
||||
use mixnet_contract_common::reward_params::IntervalRewardingParamsUpdate;
|
||||
use mixnet_contract_common::{Delegation, MixId};
|
||||
use mixnet_contract_common::{BlockHeight, Delegation, MixId};
|
||||
use vesting_contract_common::messages::ExecuteMsg as VestingContractExecuteMsg;
|
||||
|
||||
pub(crate) trait ContractExecutableEvent {
|
||||
@@ -32,6 +35,7 @@ pub(crate) trait ContractExecutableEvent {
|
||||
pub(crate) fn delegate(
|
||||
deps: DepsMut<'_>,
|
||||
env: &Env,
|
||||
created_at: BlockHeight,
|
||||
owner: Addr,
|
||||
mix_id: MixId,
|
||||
amount: Coin,
|
||||
@@ -105,7 +109,14 @@ pub(crate) fn delegate(
|
||||
// add the amount we're intending to delegate (whether it's fresh or we're adding to the existing one)
|
||||
mix_rewarding.add_base_delegation(stored_delegation_amount.amount);
|
||||
|
||||
let cosmos_event = new_delegation_event(&owner, &proxy, &new_delegation_amount, mix_id);
|
||||
let cosmos_event = new_delegation_event(
|
||||
created_at,
|
||||
&owner,
|
||||
&proxy,
|
||||
&new_delegation_amount,
|
||||
mix_id,
|
||||
mix_rewarding.total_unit_reward,
|
||||
);
|
||||
|
||||
let delegation = Delegation::new(
|
||||
owner,
|
||||
@@ -130,6 +141,7 @@ pub(crate) fn delegate(
|
||||
|
||||
pub(crate) fn undelegate(
|
||||
deps: DepsMut<'_>,
|
||||
created_at: BlockHeight,
|
||||
owner: Addr,
|
||||
mix_id: MixId,
|
||||
proxy: Option<Addr>,
|
||||
@@ -153,7 +165,7 @@ pub(crate) fn undelegate(
|
||||
let return_tokens = send_to_proxy_or_owner(&proxy, &owner, vec![tokens_to_return.clone()]);
|
||||
let mut response = Response::new()
|
||||
.add_message(return_tokens)
|
||||
.add_event(new_undelegation_event(&owner, &proxy, mix_id));
|
||||
.add_event(new_undelegation_event(created_at, &owner, &proxy, mix_id));
|
||||
|
||||
if let Some(proxy) = &proxy {
|
||||
// we can only attempt to send the message to the vesting contract if the proxy IS the vesting contract
|
||||
@@ -177,6 +189,7 @@ pub(crate) fn undelegate(
|
||||
pub(crate) fn unbond_mixnode(
|
||||
deps: DepsMut<'_>,
|
||||
env: &Env,
|
||||
created_at: BlockHeight,
|
||||
mix_id: MixId,
|
||||
) -> Result<Response, MixnetContractError> {
|
||||
// if we're here it means user executed `_try_remove_mixnode` and as a result node was set to be
|
||||
@@ -207,7 +220,7 @@ pub(crate) fn unbond_mixnode(
|
||||
|
||||
let mut response = Response::new()
|
||||
.add_message(return_tokens)
|
||||
.add_event(new_mixnode_unbonding_event(mix_id));
|
||||
.add_event(new_mixnode_unbonding_event(created_at, mix_id));
|
||||
|
||||
if let Some(proxy) = &proxy {
|
||||
// we can only attempt to send the message to the vesting contract if the proxy IS the vesting contract
|
||||
@@ -229,6 +242,7 @@ pub(crate) fn unbond_mixnode(
|
||||
|
||||
pub(crate) fn update_active_set_size(
|
||||
deps: DepsMut<'_>,
|
||||
created_at: BlockHeight,
|
||||
active_set_size: u32,
|
||||
) -> Result<Response, MixnetContractError> {
|
||||
// We don't have to check for authorization as this event can only be pushed
|
||||
@@ -241,28 +255,30 @@ pub(crate) fn update_active_set_size(
|
||||
rewarding_params.try_change_active_set_size(active_set_size)?;
|
||||
rewards_storage::REWARDING_PARAMS.save(deps.storage, &rewarding_params)?;
|
||||
|
||||
Ok(Response::new().add_event(new_active_set_update_event(active_set_size)))
|
||||
Ok(Response::new().add_event(new_active_set_update_event(created_at, active_set_size)))
|
||||
}
|
||||
|
||||
impl ContractExecutableEvent for PendingEpochEventData {
|
||||
fn execute(self, deps: DepsMut<'_>, env: &Env) -> Result<Response, MixnetContractError> {
|
||||
// note that the basic validation on all those events was already performed before
|
||||
// they were pushed onto the queue
|
||||
match self {
|
||||
PendingEpochEventData::Delegate {
|
||||
match self.kind {
|
||||
PendingEpochEventKind::Delegate {
|
||||
owner,
|
||||
mix_id,
|
||||
amount,
|
||||
proxy,
|
||||
} => delegate(deps, env, owner, mix_id, amount, proxy),
|
||||
PendingEpochEventData::Undelegate {
|
||||
} => delegate(deps, env, self.created_at, owner, mix_id, amount, proxy),
|
||||
PendingEpochEventKind::Undelegate {
|
||||
owner,
|
||||
mix_id,
|
||||
proxy,
|
||||
} => undelegate(deps, owner, mix_id, proxy),
|
||||
PendingEpochEventData::UnbondMixnode { mix_id } => unbond_mixnode(deps, env, mix_id),
|
||||
PendingEpochEventData::UpdateActiveSetSize { new_size } => {
|
||||
update_active_set_size(deps, new_size)
|
||||
} => undelegate(deps, self.created_at, owner, mix_id, proxy),
|
||||
PendingEpochEventKind::UnbondMixnode { mix_id } => {
|
||||
unbond_mixnode(deps, env, self.created_at, mix_id)
|
||||
}
|
||||
PendingEpochEventKind::UpdateActiveSetSize { new_size } => {
|
||||
update_active_set_size(deps, self.created_at, new_size)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -270,6 +286,7 @@ impl ContractExecutableEvent for PendingEpochEventData {
|
||||
|
||||
pub(crate) fn change_mix_cost_params(
|
||||
deps: DepsMut<'_>,
|
||||
created_at: BlockHeight,
|
||||
mix_id: MixId,
|
||||
new_costs: MixNodeCostParams,
|
||||
) -> Result<Response, MixnetContractError> {
|
||||
@@ -285,7 +302,7 @@ pub(crate) fn change_mix_cost_params(
|
||||
_ => return Ok(Response::default()),
|
||||
};
|
||||
|
||||
let cosmos_event = new_mixnode_cost_params_update_event(mix_id, &new_costs);
|
||||
let cosmos_event = new_mixnode_cost_params_update_event(created_at, mix_id, &new_costs);
|
||||
|
||||
// TODO: can we just change cost_params without breaking rewarding calculation?
|
||||
// (I'm almost certain we can, but well, it has to be tested)
|
||||
@@ -297,6 +314,7 @@ pub(crate) fn change_mix_cost_params(
|
||||
|
||||
pub(crate) fn update_rewarding_params(
|
||||
deps: DepsMut<'_>,
|
||||
created_at: BlockHeight,
|
||||
updated_params: IntervalRewardingParamsUpdate,
|
||||
) -> Result<Response, MixnetContractError> {
|
||||
// We don't have to check for authorization as this event can only be pushed
|
||||
@@ -311,6 +329,7 @@ pub(crate) fn update_rewarding_params(
|
||||
rewards_storage::REWARDING_PARAMS.save(deps.storage, &rewarding_params)?;
|
||||
|
||||
Ok(Response::new().add_event(new_rewarding_params_update_event(
|
||||
created_at,
|
||||
updated_params,
|
||||
rewarding_params.interval,
|
||||
)))
|
||||
@@ -318,6 +337,7 @@ pub(crate) fn update_rewarding_params(
|
||||
|
||||
pub(crate) fn update_interval_config(
|
||||
deps: DepsMut,
|
||||
created_at: BlockHeight,
|
||||
epochs_in_interval: u32,
|
||||
epoch_duration_secs: u64,
|
||||
) -> Result<Response, MixnetContractError> {
|
||||
@@ -326,8 +346,10 @@ pub(crate) fn update_interval_config(
|
||||
// Furthermore, we don't need to check whether the interval is finished as the
|
||||
// queue is only emptied upon the interval finishing.
|
||||
let interval = storage::current_interval(deps.storage)?;
|
||||
|
||||
change_interval_config(
|
||||
deps.storage,
|
||||
created_at,
|
||||
interval,
|
||||
epochs_in_interval,
|
||||
epoch_duration_secs,
|
||||
@@ -338,18 +360,23 @@ impl ContractExecutableEvent for PendingIntervalEventData {
|
||||
fn execute(self, deps: DepsMut<'_>, _env: &Env) -> Result<Response, MixnetContractError> {
|
||||
// note that the basic validation on all those events was already performed before
|
||||
// they were pushed onto the queue
|
||||
match self {
|
||||
PendingIntervalEventData::ChangeMixCostParams {
|
||||
match self.kind {
|
||||
PendingIntervalEventKind::ChangeMixCostParams {
|
||||
mix_id: mix,
|
||||
new_costs,
|
||||
} => change_mix_cost_params(deps, mix, new_costs),
|
||||
PendingIntervalEventData::UpdateRewardingParams { update } => {
|
||||
update_rewarding_params(deps, update)
|
||||
} => change_mix_cost_params(deps, self.created_at, mix, new_costs),
|
||||
PendingIntervalEventKind::UpdateRewardingParams { update } => {
|
||||
update_rewarding_params(deps, self.created_at, update)
|
||||
}
|
||||
PendingIntervalEventData::UpdateIntervalConfig {
|
||||
PendingIntervalEventKind::UpdateIntervalConfig {
|
||||
epochs_in_interval,
|
||||
epoch_duration_secs,
|
||||
} => update_interval_config(deps, epochs_in_interval, epoch_duration_secs),
|
||||
} => update_interval_config(
|
||||
deps,
|
||||
self.created_at,
|
||||
epochs_in_interval,
|
||||
epoch_duration_secs,
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -390,11 +417,12 @@ mod tests {
|
||||
test.add_immediate_delegation(owner1, delegation, mix_id);
|
||||
|
||||
let env = test.env();
|
||||
unbond_mixnode(test.deps_mut(), &env, mix_id).unwrap();
|
||||
unbond_mixnode(test.deps_mut(), &env, 123, mix_id).unwrap();
|
||||
|
||||
let res_increase = delegate(
|
||||
test.deps_mut(),
|
||||
&env,
|
||||
123,
|
||||
Addr::unchecked(owner1),
|
||||
mix_id,
|
||||
delegation_coin.clone(),
|
||||
@@ -420,6 +448,7 @@ mod tests {
|
||||
let res_fresh = delegate(
|
||||
test.deps_mut(),
|
||||
&env,
|
||||
123,
|
||||
Addr::unchecked(owner2),
|
||||
mix_id,
|
||||
delegation_coin.clone(),
|
||||
@@ -453,11 +482,12 @@ mod tests {
|
||||
test.add_immediate_delegation(owner1, delegation, mix_id);
|
||||
|
||||
let env = test.env();
|
||||
try_remove_mixnode(test.deps_mut(), mock_info("mix-owner", &[])).unwrap();
|
||||
try_remove_mixnode(test.deps_mut(), env.clone(), mock_info("mix-owner", &[])).unwrap();
|
||||
|
||||
let res_increase = delegate(
|
||||
test.deps_mut(),
|
||||
&env,
|
||||
123,
|
||||
Addr::unchecked(owner1),
|
||||
mix_id,
|
||||
delegation_coin.clone(),
|
||||
@@ -483,6 +513,7 @@ mod tests {
|
||||
let res_fresh = delegate(
|
||||
test.deps_mut(),
|
||||
&env,
|
||||
123,
|
||||
Addr::unchecked(owner2),
|
||||
mix_id,
|
||||
delegation_coin.clone(),
|
||||
@@ -518,6 +549,7 @@ mod tests {
|
||||
let res = delegate(
|
||||
test.deps_mut(),
|
||||
&env,
|
||||
123,
|
||||
Addr::unchecked(owner),
|
||||
mix_id,
|
||||
delegation_coin_new,
|
||||
@@ -580,6 +612,7 @@ mod tests {
|
||||
let res = delegate(
|
||||
test.deps_mut(),
|
||||
&env,
|
||||
123,
|
||||
Addr::unchecked(owner),
|
||||
mix_id,
|
||||
delegation_coin_new,
|
||||
@@ -645,6 +678,7 @@ mod tests {
|
||||
let res = delegate(
|
||||
test.deps_mut(),
|
||||
&env,
|
||||
123,
|
||||
Addr::unchecked(owner),
|
||||
mix_id,
|
||||
delegation_coin.clone(),
|
||||
@@ -679,7 +713,7 @@ mod tests {
|
||||
let owner2 = "delegator2";
|
||||
|
||||
let env = test.env();
|
||||
unbond_mixnode(test.deps_mut(), &env, mix_id).unwrap();
|
||||
unbond_mixnode(test.deps_mut(), &env, 123, mix_id).unwrap();
|
||||
|
||||
let vesting_contract = test.vesting_contract();
|
||||
let dummy_proxy = Addr::unchecked("not-vesting-contract");
|
||||
@@ -688,6 +722,7 @@ mod tests {
|
||||
let res_vesting = delegate(
|
||||
test.deps_mut(),
|
||||
&env,
|
||||
123,
|
||||
Addr::unchecked(owner1),
|
||||
mix_id,
|
||||
delegation_coin.clone(),
|
||||
@@ -734,6 +769,7 @@ mod tests {
|
||||
let res_other_proxy = delegate(
|
||||
test.deps_mut(),
|
||||
&env,
|
||||
123,
|
||||
Addr::unchecked(owner1),
|
||||
mix_id,
|
||||
delegation_coin.clone(),
|
||||
@@ -778,7 +814,7 @@ mod tests {
|
||||
|
||||
let owner = Addr::unchecked("delegator");
|
||||
|
||||
let res = undelegate(test.deps_mut(), owner, mix_id, None).unwrap();
|
||||
let res = undelegate(test.deps_mut(), 123, owner, mix_id, None).unwrap();
|
||||
assert!(get_bank_send_msg(&res).is_none());
|
||||
}
|
||||
|
||||
@@ -793,7 +829,7 @@ mod tests {
|
||||
// this should never happen in actual code, but if we manually messed something up,
|
||||
// lets make sure this throws an error
|
||||
rewards_storage::MIXNODE_REWARDING.remove(test.deps_mut().storage, mix_id);
|
||||
let res = undelegate(test.deps_mut(), owner, mix_id, None);
|
||||
let res = undelegate(test.deps_mut(), 123, owner, mix_id, None);
|
||||
assert!(matches!(
|
||||
res,
|
||||
Err(MixnetContractError::InconsistentState { .. })
|
||||
@@ -827,7 +863,8 @@ mod tests {
|
||||
|
||||
let expected_return = delegation + truncated_reward.u128();
|
||||
|
||||
let res = undelegate(test.deps_mut(), Addr::unchecked(owner), mix_id, None).unwrap();
|
||||
let res =
|
||||
undelegate(test.deps_mut(), 123, Addr::unchecked(owner), mix_id, None).unwrap();
|
||||
let (receiver, sent_amount) = get_bank_send_msg(&res).unwrap();
|
||||
assert_eq!(receiver, owner);
|
||||
assert_eq!(sent_amount[0].amount.u128(), expected_return);
|
||||
@@ -875,6 +912,7 @@ mod tests {
|
||||
// for a fresh delegation, nothing was added to the storage either
|
||||
let res_vesting = undelegate(
|
||||
test.deps_mut(),
|
||||
123,
|
||||
Addr::unchecked(owner1),
|
||||
mix_id,
|
||||
Some(vesting_contract.clone()),
|
||||
@@ -920,6 +958,7 @@ mod tests {
|
||||
|
||||
let res_other_proxy = undelegate(
|
||||
test.deps_mut(),
|
||||
123,
|
||||
Addr::unchecked(owner2),
|
||||
mix_id,
|
||||
Some(dummy_proxy.clone()),
|
||||
@@ -964,7 +1003,7 @@ mod tests {
|
||||
let mut test = TestSetup::new();
|
||||
let env = test.env();
|
||||
|
||||
let res = unbond_mixnode(test.deps_mut(), &env, 1);
|
||||
let res = unbond_mixnode(test.deps_mut(), &env, 123, 1);
|
||||
assert!(matches!(
|
||||
res,
|
||||
Err(MixnetContractError::InconsistentState { .. })
|
||||
@@ -994,7 +1033,7 @@ mod tests {
|
||||
let expected_return = pledge + truncated_reward;
|
||||
|
||||
let env = test.env();
|
||||
let res = unbond_mixnode(test.deps_mut(), &env, mix_id).unwrap();
|
||||
let res = unbond_mixnode(test.deps_mut(), &env, 123, mix_id).unwrap();
|
||||
let (receiver, sent_amount) = get_bank_send_msg(&res).unwrap();
|
||||
assert_eq!(receiver, owner);
|
||||
assert_eq!(sent_amount[0].amount, expected_return);
|
||||
@@ -1042,7 +1081,7 @@ mod tests {
|
||||
test.add_dummy_mixnode_with_proxy(owner2, Some(pledge), dummy_proxy.clone());
|
||||
|
||||
let env = test.env();
|
||||
let res_vesting = unbond_mixnode(test.deps_mut(), &env, mix_id_vesting).unwrap();
|
||||
let res_vesting = unbond_mixnode(test.deps_mut(), &env, 123, mix_id_vesting).unwrap();
|
||||
|
||||
assert!(mixnodes_storage::mixnode_bonds()
|
||||
.may_load(test.deps().storage, mix_id_vesting)
|
||||
@@ -1077,7 +1116,7 @@ mod tests {
|
||||
assert!(found_track);
|
||||
|
||||
let res_other_proxy =
|
||||
unbond_mixnode(test.deps_mut(), &env, mix_id_other_proxy).unwrap();
|
||||
unbond_mixnode(test.deps_mut(), &env, 123, mix_id_other_proxy).unwrap();
|
||||
assert!(mixnodes_storage::mixnode_bonds()
|
||||
.may_load(test.deps().storage, mix_id_other_proxy)
|
||||
.unwrap()
|
||||
@@ -1103,7 +1142,7 @@ mod tests {
|
||||
.load(test.deps().storage)
|
||||
.unwrap();
|
||||
|
||||
update_active_set_size(test.deps_mut(), 50).unwrap();
|
||||
update_active_set_size(test.deps_mut(), 123, 50).unwrap();
|
||||
let updated = rewards_storage::REWARDING_PARAMS
|
||||
.load(test.deps().storage)
|
||||
.unwrap();
|
||||
@@ -1124,14 +1163,14 @@ mod tests {
|
||||
let mix_id = test.add_dummy_mixnode("mix-owner", None);
|
||||
|
||||
let env = test.env();
|
||||
unbond_mixnode(test.deps_mut(), &env, mix_id).unwrap();
|
||||
unbond_mixnode(test.deps_mut(), &env, 123, mix_id).unwrap();
|
||||
|
||||
let new_params = MixNodeCostParams {
|
||||
profit_margin_percent: Percent::from_percentage_value(42).unwrap(),
|
||||
interval_operating_cost: coin(123_456_789, TEST_COIN_DENOM),
|
||||
};
|
||||
|
||||
let res = change_mix_cost_params(test.deps_mut(), mix_id, new_params);
|
||||
let res = change_mix_cost_params(test.deps_mut(), 123, mix_id, new_params);
|
||||
assert_eq!(res, Ok(Response::default()));
|
||||
}
|
||||
|
||||
@@ -1147,11 +1186,16 @@ mod tests {
|
||||
interval_operating_cost: coin(123_456_789, TEST_COIN_DENOM),
|
||||
};
|
||||
|
||||
let res = change_mix_cost_params(test.deps_mut(), mix_id, new_params.clone());
|
||||
let res = change_mix_cost_params(test.deps_mut(), 123, mix_id, new_params.clone());
|
||||
assert_eq!(
|
||||
res,
|
||||
Ok(Response::new()
|
||||
.add_event(new_mixnode_cost_params_update_event(mix_id, &new_params)))
|
||||
Ok(
|
||||
Response::new().add_event(new_mixnode_cost_params_update_event(
|
||||
123,
|
||||
mix_id,
|
||||
&new_params
|
||||
))
|
||||
)
|
||||
);
|
||||
|
||||
let after = test.mix_rewarding(mix_id).cost_params;
|
||||
@@ -1182,7 +1226,7 @@ mod tests {
|
||||
rewarded_set_size: None,
|
||||
};
|
||||
|
||||
let res = update_rewarding_params(test.deps_mut(), update);
|
||||
let res = update_rewarding_params(test.deps_mut(), 123, update);
|
||||
assert!(res.is_ok());
|
||||
let after = rewards_storage::REWARDING_PARAMS
|
||||
.load(test.deps().storage)
|
||||
@@ -1230,6 +1274,7 @@ mod tests {
|
||||
// and change epoch length
|
||||
update_interval_config(
|
||||
test.deps_mut(),
|
||||
123,
|
||||
interval_before.epochs_in_interval() / 2,
|
||||
1234,
|
||||
)
|
||||
|
||||
@@ -238,7 +238,7 @@ mod tests {
|
||||
mod pending_epoch_events {
|
||||
use super::*;
|
||||
use cosmwasm_std::Addr;
|
||||
use mixnet_contract_common::pending_events::PendingEpochEventData;
|
||||
use mixnet_contract_common::pending_events::PendingEpochEventKind;
|
||||
use rand_chacha::rand_core::RngCore;
|
||||
|
||||
fn push_n_dummy_epoch_actions(test: &mut TestSetup, n: usize) {
|
||||
@@ -248,12 +248,13 @@ mod tests {
|
||||
}
|
||||
|
||||
fn push_dummy_epoch_action(test: &mut TestSetup) {
|
||||
let dummy_action = PendingEpochEventData::Undelegate {
|
||||
let dummy_action = PendingEpochEventKind::Undelegate {
|
||||
owner: Addr::unchecked("foomp"),
|
||||
mix_id: test.rng.next_u32(),
|
||||
proxy: None,
|
||||
};
|
||||
storage::push_new_epoch_event(test.deps_mut().storage, &dummy_action).unwrap();
|
||||
let env = test.env();
|
||||
storage::push_new_epoch_event(test.deps_mut().storage, &env, dummy_action).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -379,7 +380,7 @@ mod tests {
|
||||
mod pending_interval_events {
|
||||
use super::*;
|
||||
use crate::support::tests::fixtures;
|
||||
use mixnet_contract_common::pending_events::PendingIntervalEventData;
|
||||
use mixnet_contract_common::pending_events::PendingIntervalEventKind;
|
||||
use rand_chacha::rand_core::RngCore;
|
||||
|
||||
fn push_n_dummy_interval_actions(test: &mut TestSetup, n: usize) {
|
||||
@@ -389,11 +390,12 @@ mod tests {
|
||||
}
|
||||
|
||||
fn push_dummy_interval_action(test: &mut TestSetup) {
|
||||
let dummy_action = PendingIntervalEventData::ChangeMixCostParams {
|
||||
let dummy_action = PendingIntervalEventKind::ChangeMixCostParams {
|
||||
mix_id: test.rng.next_u32(),
|
||||
new_costs: fixtures::mix_node_cost_params_fixture(),
|
||||
};
|
||||
storage::push_new_interval_event(test.deps_mut().storage, &dummy_action).unwrap();
|
||||
let env = test.env();
|
||||
storage::push_new_interval_event(test.deps_mut().storage, &env, dummy_action).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -6,11 +6,13 @@ use crate::constants::{
|
||||
LAST_EPOCH_EVENT_ID_KEY, LAST_INTERVAL_EVENT_ID_KEY, PENDING_EPOCH_EVENTS_NAMESPACE,
|
||||
PENDING_INTERVAL_EVENTS_NAMESPACE, REWARDED_SET_KEY,
|
||||
};
|
||||
use cosmwasm_std::{Order, StdResult, Storage};
|
||||
use cosmwasm_std::{Env, Order, StdResult, Storage};
|
||||
use cw_storage_plus::{Item, Map};
|
||||
use mixnet_contract_common::pending_events::{PendingEpochEventData, PendingIntervalEventData};
|
||||
use mixnet_contract_common::pending_events::{
|
||||
PendingEpochEventData, PendingEpochEventKind, PendingIntervalEventData,
|
||||
};
|
||||
use mixnet_contract_common::{
|
||||
EpochEventId, Interval, IntervalEventId, MixId, RewardedSetNodeStatus,
|
||||
EpochEventId, Interval, IntervalEventId, MixId, PendingIntervalEventKind, RewardedSetNodeStatus,
|
||||
};
|
||||
use std::collections::HashMap;
|
||||
|
||||
@@ -64,18 +66,22 @@ pub(crate) fn next_interval_event_id_counter(
|
||||
|
||||
pub(crate) fn push_new_epoch_event(
|
||||
storage: &mut dyn Storage,
|
||||
event: &PendingEpochEventData,
|
||||
env: &Env,
|
||||
event: PendingEpochEventKind,
|
||||
) -> StdResult<()> {
|
||||
let event_id = next_epoch_event_id_counter(storage)?;
|
||||
PENDING_EPOCH_EVENTS.save(storage, event_id, event)
|
||||
let event_data = event.attach_source_height(env.block.height);
|
||||
PENDING_EPOCH_EVENTS.save(storage, event_id, &event_data)
|
||||
}
|
||||
|
||||
pub(crate) fn push_new_interval_event(
|
||||
storage: &mut dyn Storage,
|
||||
event: &PendingIntervalEventData,
|
||||
env: &Env,
|
||||
event: PendingIntervalEventKind,
|
||||
) -> StdResult<()> {
|
||||
let event_id = next_interval_event_id_counter(storage)?;
|
||||
PENDING_INTERVAL_EVENTS.save(storage, event_id, event)
|
||||
let event_data = event.attach_source_height(env.block.height);
|
||||
PENDING_INTERVAL_EVENTS.save(storage, event_id, &event_data)
|
||||
}
|
||||
|
||||
pub(crate) fn update_rewarded_set(
|
||||
|
||||
@@ -15,7 +15,7 @@ use mixnet_contract_common::events::{
|
||||
new_pending_interval_config_update_event, new_pending_interval_events_execution_event,
|
||||
new_reconcile_pending_events,
|
||||
};
|
||||
use mixnet_contract_common::pending_events::PendingIntervalEventData;
|
||||
use mixnet_contract_common::pending_events::PendingIntervalEventKind;
|
||||
use mixnet_contract_common::MixId;
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
@@ -270,17 +270,18 @@ pub(crate) fn try_update_interval_config(
|
||||
if force_immediately || interval.is_current_interval_over(&env) {
|
||||
change_interval_config(
|
||||
deps.storage,
|
||||
env.block.height,
|
||||
interval,
|
||||
epochs_in_interval,
|
||||
epoch_duration_secs,
|
||||
)
|
||||
} else {
|
||||
// push the interval event
|
||||
let interval_event = PendingIntervalEventData::UpdateIntervalConfig {
|
||||
let interval_event = PendingIntervalEventKind::UpdateIntervalConfig {
|
||||
epochs_in_interval,
|
||||
epoch_duration_secs,
|
||||
};
|
||||
push_new_interval_event(deps.storage, &interval_event)?;
|
||||
push_new_interval_event(deps.storage, &env, interval_event)?;
|
||||
let time_left = interval.secs_until_current_interval_end(&env);
|
||||
Ok(
|
||||
Response::new().add_event(new_pending_interval_config_update_event(
|
||||
@@ -298,31 +299,33 @@ mod tests {
|
||||
use crate::support::tests::fixtures;
|
||||
use crate::support::tests::test_helpers::TestSetup;
|
||||
use cosmwasm_std::Addr;
|
||||
use mixnet_contract_common::pending_events::PendingEpochEventData;
|
||||
use mixnet_contract_common::pending_events::PendingEpochEventKind;
|
||||
use vesting_contract_common::messages::ExecuteMsg as VestingContractExecuteMsg;
|
||||
|
||||
fn push_n_dummy_epoch_actions(test: &mut TestSetup, n: usize) {
|
||||
// if you attempt to undelegate non-existent delegation,
|
||||
// it will return an empty response, but will not fail
|
||||
let env = test.env();
|
||||
for i in 0..n {
|
||||
let dummy_action = PendingEpochEventData::Undelegate {
|
||||
let dummy_action = PendingEpochEventKind::Undelegate {
|
||||
owner: Addr::unchecked("foomp"),
|
||||
mix_id: i as MixId,
|
||||
proxy: None,
|
||||
};
|
||||
storage::push_new_epoch_event(test.deps_mut().storage, &dummy_action).unwrap();
|
||||
storage::push_new_epoch_event(test.deps_mut().storage, &env, dummy_action).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
fn push_n_dummy_interval_actions(test: &mut TestSetup, n: usize) {
|
||||
// if you attempt to update cost parameters of an unbonded mixnode,
|
||||
// it will return an empty response, but will not fail
|
||||
let env = test.env();
|
||||
for i in 0..n {
|
||||
let dummy_action = PendingIntervalEventData::ChangeMixCostParams {
|
||||
let dummy_action = PendingIntervalEventKind::ChangeMixCostParams {
|
||||
mix_id: i as MixId,
|
||||
new_costs: fixtures::mix_node_cost_params_fixture(),
|
||||
};
|
||||
storage::push_new_interval_event(test.deps_mut().storage, &dummy_action).unwrap();
|
||||
storage::push_new_interval_event(test.deps_mut().storage, &env, dummy_action).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -335,7 +338,7 @@ mod tests {
|
||||
new_active_set_update_event, new_delegation_on_unbonded_node_event,
|
||||
new_undelegation_event,
|
||||
};
|
||||
use mixnet_contract_common::pending_events::PendingEpochEventData;
|
||||
use mixnet_contract_common::pending_events::PendingEpochEventKind;
|
||||
|
||||
#[test]
|
||||
fn without_limit_executes_all_actions() {
|
||||
@@ -398,14 +401,15 @@ mod tests {
|
||||
);
|
||||
|
||||
push_n_dummy_epoch_actions(&mut test, 10);
|
||||
let action_with_event = PendingEpochEventData::UpdateActiveSetSize { new_size: 50 };
|
||||
storage::push_new_epoch_event(test.deps_mut().storage, &action_with_event).unwrap();
|
||||
let action_with_event = PendingEpochEventKind::UpdateActiveSetSize { new_size: 50 };
|
||||
storage::push_new_epoch_event(test.deps_mut().storage, &env, action_with_event)
|
||||
.unwrap();
|
||||
push_n_dummy_epoch_actions(&mut test, 10);
|
||||
let (res, executed) =
|
||||
perform_pending_epoch_actions(test.deps_mut(), &env, None).unwrap();
|
||||
assert_eq!(
|
||||
res,
|
||||
Response::new().add_event(new_active_set_update_event(50))
|
||||
Response::new().add_event(new_active_set_update_event(env.block.height, 50))
|
||||
);
|
||||
assert_eq!(executed, 21);
|
||||
assert_eq!(
|
||||
@@ -433,13 +437,13 @@ mod tests {
|
||||
// delegate to node that doesn't exist,
|
||||
// we expect to receive BankMsg with tokens being returned,
|
||||
// and event regarding delegation
|
||||
let non_existent_delegation = PendingEpochEventData::Delegate {
|
||||
let non_existent_delegation = PendingEpochEventKind::Delegate {
|
||||
owner: Addr::unchecked("foomp"),
|
||||
mix_id: 123,
|
||||
amount: coin(123, TEST_COIN_DENOM),
|
||||
proxy: None,
|
||||
};
|
||||
storage::push_new_epoch_event(test.deps_mut().storage, &non_existent_delegation)
|
||||
storage::push_new_epoch_event(test.deps_mut().storage, &env, non_existent_delegation)
|
||||
.unwrap();
|
||||
expected_events.push(new_delegation_on_unbonded_node_event(
|
||||
&Addr::unchecked("foomp"),
|
||||
@@ -453,13 +457,13 @@ mod tests {
|
||||
|
||||
// delegation to node that doesn't exist with vesting contract
|
||||
// we expect the same as above PLUS TrackUndelegation message
|
||||
let non_existent_delegation = PendingEpochEventData::Delegate {
|
||||
let non_existent_delegation = PendingEpochEventKind::Delegate {
|
||||
owner: Addr::unchecked("foomp2"),
|
||||
mix_id: 123,
|
||||
amount: coin(123, TEST_COIN_DENOM),
|
||||
proxy: Some(vesting_contract.clone()),
|
||||
};
|
||||
storage::push_new_epoch_event(test.deps_mut().storage, &non_existent_delegation)
|
||||
storage::push_new_epoch_event(test.deps_mut().storage, &env, non_existent_delegation)
|
||||
.unwrap();
|
||||
expected_events.push(new_delegation_on_unbonded_node_event(
|
||||
&Addr::unchecked("foomp2"),
|
||||
@@ -479,18 +483,24 @@ mod tests {
|
||||
expected_messages.push(SubMsg::new(track_undelegate_message));
|
||||
|
||||
// updating active set should only emit events and no cosmos messages
|
||||
let action_with_event = PendingEpochEventData::UpdateActiveSetSize { new_size: 50 };
|
||||
storage::push_new_epoch_event(test.deps_mut().storage, &action_with_event).unwrap();
|
||||
expected_events.push(new_active_set_update_event(50));
|
||||
let action_with_event = PendingEpochEventKind::UpdateActiveSetSize { new_size: 50 };
|
||||
storage::push_new_epoch_event(test.deps_mut().storage, &env, action_with_event)
|
||||
.unwrap();
|
||||
expected_events.push(new_active_set_update_event(env.block.height, 50));
|
||||
|
||||
// undelegation just returns tokens and emits event
|
||||
let legit_undelegate = PendingEpochEventData::Undelegate {
|
||||
let legit_undelegate = PendingEpochEventKind::Undelegate {
|
||||
owner: delegator.clone(),
|
||||
mix_id: legit_mix,
|
||||
proxy: None,
|
||||
};
|
||||
storage::push_new_epoch_event(test.deps_mut().storage, &legit_undelegate).unwrap();
|
||||
expected_events.push(new_undelegation_event(&delegator, &None, legit_mix));
|
||||
storage::push_new_epoch_event(test.deps_mut().storage, &env, legit_undelegate).unwrap();
|
||||
expected_events.push(new_undelegation_event(
|
||||
env.block.height,
|
||||
&delegator,
|
||||
&None,
|
||||
legit_mix,
|
||||
));
|
||||
expected_messages.push(SubMsg::new(BankMsg::Send {
|
||||
to_address: delegator.into_string(),
|
||||
amount: coins(amount, TEST_COIN_DENOM),
|
||||
@@ -640,16 +650,20 @@ mod tests {
|
||||
rewarded_set_size: Some(500),
|
||||
..Default::default()
|
||||
};
|
||||
let action_with_event = PendingIntervalEventData::UpdateRewardingParams { update };
|
||||
storage::push_new_interval_event(test.deps_mut().storage, &action_with_event).unwrap();
|
||||
let action_with_event = PendingIntervalEventKind::UpdateRewardingParams { update };
|
||||
storage::push_new_interval_event(test.deps_mut().storage, &env, action_with_event)
|
||||
.unwrap();
|
||||
push_n_dummy_interval_actions(&mut test, 10);
|
||||
let (res, executed) =
|
||||
perform_pending_interval_actions(test.deps_mut(), &env, None).unwrap();
|
||||
let updated_params = test.rewarding_params().interval;
|
||||
assert_eq!(
|
||||
res,
|
||||
Response::new()
|
||||
.add_event(new_rewarding_params_update_event(update, updated_params))
|
||||
Response::new().add_event(new_rewarding_params_update_event(
|
||||
env.block.height,
|
||||
update,
|
||||
updated_params
|
||||
))
|
||||
);
|
||||
assert_eq!(executed, 21);
|
||||
assert_eq!(
|
||||
@@ -673,38 +687,45 @@ mod tests {
|
||||
profit_margin_percent: Percent::from_percentage_value(12).unwrap(),
|
||||
interval_operating_cost: coin(123_000, TEST_COIN_DENOM),
|
||||
};
|
||||
let cost_change = PendingIntervalEventData::ChangeMixCostParams {
|
||||
let cost_change = PendingIntervalEventKind::ChangeMixCostParams {
|
||||
mix_id: legit_mix,
|
||||
new_costs: new_costs.clone(),
|
||||
};
|
||||
|
||||
storage::push_new_interval_event(test.deps_mut().storage, &cost_change).unwrap();
|
||||
expected_events.push(new_mixnode_cost_params_update_event(legit_mix, &new_costs));
|
||||
storage::push_new_interval_event(test.deps_mut().storage, &env, cost_change).unwrap();
|
||||
expected_events.push(new_mixnode_cost_params_update_event(
|
||||
env.block.height,
|
||||
legit_mix,
|
||||
&new_costs,
|
||||
));
|
||||
|
||||
let update = IntervalRewardingParamsUpdate {
|
||||
rewarded_set_size: Some(500),
|
||||
..Default::default()
|
||||
};
|
||||
let change_params = PendingIntervalEventData::UpdateRewardingParams { update };
|
||||
storage::push_new_interval_event(test.deps_mut().storage, &change_params).unwrap();
|
||||
let change_params = PendingIntervalEventKind::UpdateRewardingParams { update };
|
||||
storage::push_new_interval_event(test.deps_mut().storage, &env, change_params).unwrap();
|
||||
let interval = test.current_interval();
|
||||
let mut expected_updated = test.rewarding_params();
|
||||
expected_updated
|
||||
.try_apply_updates(update, interval.epochs_in_interval())
|
||||
.unwrap();
|
||||
expected_events.push(new_rewarding_params_update_event(
|
||||
env.block.height,
|
||||
update,
|
||||
expected_updated.interval,
|
||||
));
|
||||
|
||||
let change_interval = PendingIntervalEventData::UpdateIntervalConfig {
|
||||
let change_interval = PendingIntervalEventKind::UpdateIntervalConfig {
|
||||
epochs_in_interval: 123,
|
||||
epoch_duration_secs: 1000,
|
||||
};
|
||||
let mut expected_updated2 = expected_updated;
|
||||
expected_updated2.apply_epochs_in_interval_change(123);
|
||||
storage::push_new_interval_event(test.deps_mut().storage, &change_interval).unwrap();
|
||||
storage::push_new_interval_event(test.deps_mut().storage, &env, change_interval)
|
||||
.unwrap();
|
||||
expected_events.push(new_interval_config_update_event(
|
||||
env.block.height,
|
||||
123,
|
||||
1000,
|
||||
expected_updated2.interval,
|
||||
@@ -785,7 +806,7 @@ mod tests {
|
||||
use mixnet_contract_common::events::{
|
||||
new_delegation_on_unbonded_node_event, new_rewarding_params_update_event,
|
||||
};
|
||||
use mixnet_contract_common::pending_events::PendingEpochEventData;
|
||||
use mixnet_contract_common::pending_events::PendingEpochEventKind;
|
||||
use mixnet_contract_common::reward_params::IntervalRewardingParamsUpdate;
|
||||
|
||||
#[test]
|
||||
@@ -967,18 +988,19 @@ mod tests {
|
||||
#[test]
|
||||
fn catches_all_emitted_cosmos_events_and_messages() {
|
||||
let mut test = TestSetup::new();
|
||||
let env = test.env();
|
||||
|
||||
let mut expected_events = vec![new_reconcile_pending_events()];
|
||||
let mut expected_messages: Vec<SubMsg<Empty>> = Vec::new();
|
||||
|
||||
// epoch event
|
||||
let non_existent_delegation = PendingEpochEventData::Delegate {
|
||||
let non_existent_delegation = PendingEpochEventKind::Delegate {
|
||||
owner: Addr::unchecked("foomp"),
|
||||
mix_id: 123,
|
||||
amount: coin(123, TEST_COIN_DENOM),
|
||||
proxy: None,
|
||||
};
|
||||
storage::push_new_epoch_event(test.deps_mut().storage, &non_existent_delegation)
|
||||
storage::push_new_epoch_event(test.deps_mut().storage, &env, non_existent_delegation)
|
||||
.unwrap();
|
||||
expected_events.push(new_delegation_on_unbonded_node_event(
|
||||
&Addr::unchecked("foomp"),
|
||||
@@ -996,14 +1018,15 @@ mod tests {
|
||||
rewarded_set_size: Some(500),
|
||||
..Default::default()
|
||||
};
|
||||
let change_params = PendingIntervalEventData::UpdateRewardingParams { update };
|
||||
storage::push_new_interval_event(test.deps_mut().storage, &change_params).unwrap();
|
||||
let change_params = PendingIntervalEventKind::UpdateRewardingParams { update };
|
||||
storage::push_new_interval_event(test.deps_mut().storage, &env, change_params).unwrap();
|
||||
let interval = test.current_interval();
|
||||
let mut expected_updated = test.rewarding_params();
|
||||
expected_updated
|
||||
.try_apply_updates(update, interval.epochs_in_interval())
|
||||
.unwrap();
|
||||
expected_events.push(new_rewarding_params_update_event(
|
||||
env.block.height,
|
||||
update,
|
||||
expected_updated.interval,
|
||||
));
|
||||
@@ -1238,18 +1261,19 @@ mod tests {
|
||||
#[test]
|
||||
fn if_executes_any_events_it_propagates_responses() {
|
||||
let mut test = TestSetup::new();
|
||||
let env = test.env();
|
||||
let current_active_set = test.rewarding_params().active_set_size;
|
||||
|
||||
let mut expected_events = Vec::new();
|
||||
let mut expected_messages: Vec<SubMsg<Empty>> = Vec::new();
|
||||
|
||||
let non_existent_delegation = PendingEpochEventData::Delegate {
|
||||
let non_existent_delegation = PendingEpochEventKind::Delegate {
|
||||
owner: Addr::unchecked("foomp"),
|
||||
mix_id: 123,
|
||||
amount: coin(123, TEST_COIN_DENOM),
|
||||
proxy: None,
|
||||
};
|
||||
storage::push_new_epoch_event(test.deps_mut().storage, &non_existent_delegation)
|
||||
storage::push_new_epoch_event(test.deps_mut().storage, &env, non_existent_delegation)
|
||||
.unwrap();
|
||||
expected_events.push(new_delegation_on_unbonded_node_event(
|
||||
&Addr::unchecked("foomp"),
|
||||
@@ -1267,14 +1291,15 @@ mod tests {
|
||||
rewarded_set_size: Some(500),
|
||||
..Default::default()
|
||||
};
|
||||
let change_params = PendingIntervalEventData::UpdateRewardingParams { update };
|
||||
storage::push_new_interval_event(test.deps_mut().storage, &change_params).unwrap();
|
||||
let change_params = PendingIntervalEventKind::UpdateRewardingParams { update };
|
||||
storage::push_new_interval_event(test.deps_mut().storage, &env, change_params).unwrap();
|
||||
let interval = test.current_interval();
|
||||
let mut expected_updated = test.rewarding_params();
|
||||
expected_updated
|
||||
.try_apply_updates(update, interval.epochs_in_interval())
|
||||
.unwrap();
|
||||
expected_events.push(new_rewarding_params_update_event(
|
||||
env.block.height,
|
||||
update,
|
||||
expected_updated.interval,
|
||||
));
|
||||
@@ -1509,8 +1534,8 @@ mod tests {
|
||||
|
||||
// make sure it's actually saved to pending events
|
||||
let events = test.pending_interval_events();
|
||||
assert!(matches!(events[0],
|
||||
PendingIntervalEventData::UpdateIntervalConfig { epochs_in_interval, epoch_duration_secs } if epochs_in_interval == 100 && epoch_duration_secs == 1000
|
||||
assert!(matches!(events[0].kind,
|
||||
PendingIntervalEventKind::UpdateIntervalConfig { epochs_in_interval, epoch_duration_secs } if epochs_in_interval == 100 && epoch_duration_secs == 1000
|
||||
));
|
||||
|
||||
test.execute_all_pending_events();
|
||||
|
||||
@@ -1174,7 +1174,7 @@ pub(crate) mod tests {
|
||||
.save(deps.as_mut().storage, id, &rewarding_details)
|
||||
.unwrap();
|
||||
|
||||
pending_events::unbond_mixnode(deps.as_mut(), &mock_env(), id).unwrap();
|
||||
pending_events::unbond_mixnode(deps.as_mut(), &mock_env(), 123, id).unwrap();
|
||||
let res = query_owned_mixnode(deps.as_ref(), address.clone()).unwrap();
|
||||
assert!(res.mixnode_details.is_none());
|
||||
assert_eq!(address, res.address);
|
||||
@@ -1263,7 +1263,7 @@ pub(crate) mod tests {
|
||||
// add and unbond the mixnode
|
||||
let mix_id =
|
||||
test_helpers::add_mixnode(&mut rng, deps.as_mut(), env, sender, good_mixnode_pledge());
|
||||
pending_events::unbond_mixnode(deps.as_mut(), &mock_env(), mix_id).unwrap();
|
||||
pending_events::unbond_mixnode(deps.as_mut(), &mock_env(), 123, mix_id).unwrap();
|
||||
|
||||
let res = query_unbonded_mixnode(deps.as_ref(), mix_id).unwrap();
|
||||
assert_eq!(res.unbonded_info.unwrap().owner, sender);
|
||||
|
||||
@@ -17,7 +17,7 @@ use mixnet_contract_common::events::{
|
||||
new_mixnode_pending_cost_params_update_event, new_pending_mixnode_unbonding_event,
|
||||
};
|
||||
use mixnet_contract_common::mixnode::{MixNodeConfigUpdate, MixNodeCostParams};
|
||||
use mixnet_contract_common::pending_events::{PendingEpochEventData, PendingIntervalEventData};
|
||||
use mixnet_contract_common::pending_events::{PendingEpochEventKind, PendingIntervalEventKind};
|
||||
use mixnet_contract_common::MixNode;
|
||||
|
||||
pub fn try_add_mixnode(
|
||||
@@ -119,23 +119,26 @@ fn _try_add_mixnode(
|
||||
|
||||
pub fn try_remove_mixnode_on_behalf(
|
||||
deps: DepsMut<'_>,
|
||||
env: Env,
|
||||
info: MessageInfo,
|
||||
owner: String,
|
||||
) -> Result<Response, MixnetContractError> {
|
||||
let proxy = info.sender;
|
||||
let owner = deps.api.addr_validate(&owner)?;
|
||||
_try_remove_mixnode(deps, owner, Some(proxy))
|
||||
_try_remove_mixnode(deps, env, owner, Some(proxy))
|
||||
}
|
||||
|
||||
pub fn try_remove_mixnode(
|
||||
deps: DepsMut<'_>,
|
||||
env: Env,
|
||||
info: MessageInfo,
|
||||
) -> Result<Response, MixnetContractError> {
|
||||
_try_remove_mixnode(deps, info.sender, None)
|
||||
_try_remove_mixnode(deps, env, info.sender, None)
|
||||
}
|
||||
|
||||
pub(crate) fn _try_remove_mixnode(
|
||||
deps: DepsMut<'_>,
|
||||
env: Env,
|
||||
owner: Addr,
|
||||
proxy: Option<Addr>,
|
||||
) -> Result<Response, MixnetContractError> {
|
||||
@@ -161,10 +164,10 @@ pub(crate) fn _try_remove_mixnode(
|
||||
)?;
|
||||
|
||||
// push the event to execute it at the end of the epoch
|
||||
let epoch_event = PendingEpochEventData::UnbondMixnode {
|
||||
let epoch_event = PendingEpochEventKind::UnbondMixnode {
|
||||
mix_id: existing_bond.mix_id,
|
||||
};
|
||||
interval_storage::push_new_epoch_event(deps.storage, &epoch_event)?;
|
||||
interval_storage::push_new_epoch_event(deps.storage, &env, epoch_event)?;
|
||||
|
||||
Ok(
|
||||
Response::new().add_event(new_pending_mixnode_unbonding_event(
|
||||
@@ -229,26 +232,29 @@ pub(crate) fn _try_update_mixnode_config(
|
||||
|
||||
pub(crate) fn try_update_mixnode_cost_params(
|
||||
deps: DepsMut<'_>,
|
||||
env: Env,
|
||||
info: MessageInfo,
|
||||
new_costs: MixNodeCostParams,
|
||||
) -> Result<Response, MixnetContractError> {
|
||||
let owner = info.sender;
|
||||
_try_update_mixnode_cost_params(deps, new_costs, owner, None)
|
||||
_try_update_mixnode_cost_params(deps, env, new_costs, owner, None)
|
||||
}
|
||||
|
||||
pub(crate) fn try_update_mixnode_cost_params_on_behalf(
|
||||
deps: DepsMut,
|
||||
env: Env,
|
||||
info: MessageInfo,
|
||||
new_costs: MixNodeCostParams,
|
||||
owner: String,
|
||||
) -> Result<Response, MixnetContractError> {
|
||||
let owner = deps.api.addr_validate(&owner)?;
|
||||
let proxy = info.sender;
|
||||
_try_update_mixnode_cost_params(deps, new_costs, owner, Some(proxy))
|
||||
_try_update_mixnode_cost_params(deps, env, new_costs, owner, Some(proxy))
|
||||
}
|
||||
|
||||
pub(crate) fn _try_update_mixnode_cost_params(
|
||||
deps: DepsMut,
|
||||
env: Env,
|
||||
new_costs: MixNodeCostParams,
|
||||
owner: Addr,
|
||||
proxy: Option<Addr>,
|
||||
@@ -267,11 +273,11 @@ pub(crate) fn _try_update_mixnode_cost_params(
|
||||
);
|
||||
|
||||
// push the interval event
|
||||
let interval_event = PendingIntervalEventData::ChangeMixCostParams {
|
||||
let interval_event = PendingIntervalEventKind::ChangeMixCostParams {
|
||||
mix_id: existing_bond.mix_id,
|
||||
new_costs,
|
||||
};
|
||||
push_new_interval_event(deps.storage, &interval_event)?;
|
||||
push_new_interval_event(deps.storage, &env, interval_event)?;
|
||||
|
||||
Ok(Response::new().add_event(cosmos_event))
|
||||
}
|
||||
@@ -418,7 +424,7 @@ pub mod tests {
|
||||
let info = mock_info(sender, &[]);
|
||||
|
||||
// trying to remove your mixnode fails if you never had one in the first place
|
||||
let res = try_remove_mixnode(deps.as_mut(), info.clone());
|
||||
let res = try_remove_mixnode(deps.as_mut(), env.clone(), info.clone());
|
||||
assert_eq!(
|
||||
res,
|
||||
Err(MixnetContractError::NoAssociatedMixNodeBond {
|
||||
@@ -426,12 +432,18 @@ pub mod tests {
|
||||
})
|
||||
);
|
||||
|
||||
let mix_id =
|
||||
test_helpers::add_mixnode(&mut rng, deps.as_mut(), env, sender, good_mixnode_pledge());
|
||||
let mix_id = test_helpers::add_mixnode(
|
||||
&mut rng,
|
||||
deps.as_mut(),
|
||||
env.clone(),
|
||||
sender,
|
||||
good_mixnode_pledge(),
|
||||
);
|
||||
|
||||
// attempted to remove on behalf with invalid proxy (current is `None`)
|
||||
let res = try_remove_mixnode_on_behalf(
|
||||
deps.as_mut(),
|
||||
env.clone(),
|
||||
mock_info("proxy", &[]),
|
||||
sender.to_string(),
|
||||
);
|
||||
@@ -444,7 +456,7 @@ pub mod tests {
|
||||
);
|
||||
|
||||
// "normal" unbonding succeeds and unbonding event is pushed to the pending epoch events
|
||||
let res = try_remove_mixnode(deps.as_mut(), info.clone());
|
||||
let res = try_remove_mixnode(deps.as_mut(), env.clone(), info.clone());
|
||||
assert!(res.is_ok());
|
||||
let mut pending_events = interval_storage::PENDING_EPOCH_EVENTS
|
||||
.range(deps.as_ref().storage, None, None, Order::Ascending)
|
||||
@@ -453,10 +465,13 @@ pub mod tests {
|
||||
assert_eq!(pending_events.len(), 1);
|
||||
let event = pending_events.pop().unwrap();
|
||||
assert_eq!(1, event.0);
|
||||
assert_eq!(PendingEpochEventData::UnbondMixnode { mix_id }, event.1);
|
||||
assert_eq!(
|
||||
PendingEpochEventKind::UnbondMixnode { mix_id },
|
||||
event.1.kind
|
||||
);
|
||||
|
||||
// but fails if repeated (since the node is already in the "unbonding" state)(
|
||||
let res = try_remove_mixnode(deps.as_mut(), info);
|
||||
let res = try_remove_mixnode(deps.as_mut(), env, info);
|
||||
assert_eq!(res, Err(MixnetContractError::MixnodeIsUnbonding { mix_id }))
|
||||
}
|
||||
|
||||
@@ -488,7 +503,7 @@ pub mod tests {
|
||||
let mix_id = test_helpers::add_mixnode(
|
||||
&mut rng,
|
||||
deps.as_mut(),
|
||||
env,
|
||||
env.clone(),
|
||||
sender,
|
||||
tests::fixtures::good_mixnode_pledge(),
|
||||
);
|
||||
@@ -521,7 +536,7 @@ pub mod tests {
|
||||
assert_eq!(mix.mix_node.version, update.version);
|
||||
|
||||
// but we cannot perform any updates whilst the mixnode is already unbonding
|
||||
try_remove_mixnode(deps.as_mut(), info.clone()).unwrap();
|
||||
try_remove_mixnode(deps.as_mut(), env, info.clone()).unwrap();
|
||||
let res = try_update_mixnode_config(deps.as_mut(), info, update);
|
||||
assert_eq!(res, Err(MixnetContractError::MixnodeIsUnbonding { mix_id }))
|
||||
}
|
||||
@@ -540,7 +555,12 @@ pub mod tests {
|
||||
};
|
||||
|
||||
// try updating a non existing mixnode bond
|
||||
let res = try_update_mixnode_cost_params(deps.as_mut(), info.clone(), update.clone());
|
||||
let res = try_update_mixnode_cost_params(
|
||||
deps.as_mut(),
|
||||
env.clone(),
|
||||
info.clone(),
|
||||
update.clone(),
|
||||
);
|
||||
assert_eq!(
|
||||
res,
|
||||
Err(MixnetContractError::NoAssociatedMixNodeBond {
|
||||
@@ -559,6 +579,7 @@ pub mod tests {
|
||||
// attempted to remove on behalf with invalid proxy (current is `None`)
|
||||
let res = try_update_mixnode_cost_params_on_behalf(
|
||||
deps.as_mut(),
|
||||
env.clone(),
|
||||
mock_info("proxy", &[]),
|
||||
update.clone(),
|
||||
sender.to_string(),
|
||||
@@ -571,7 +592,12 @@ pub mod tests {
|
||||
})
|
||||
);
|
||||
// "normal" update succeeds
|
||||
let res = try_update_mixnode_cost_params(deps.as_mut(), info.clone(), update.clone());
|
||||
let res = try_update_mixnode_cost_params(
|
||||
deps.as_mut(),
|
||||
env.clone(),
|
||||
info.clone(),
|
||||
update.clone(),
|
||||
);
|
||||
assert!(res.is_ok());
|
||||
|
||||
// see if the event has been pushed onto the queue
|
||||
@@ -583,15 +609,15 @@ pub mod tests {
|
||||
let event = pending_events.pop().unwrap();
|
||||
assert_eq!(1, event.0);
|
||||
assert_eq!(
|
||||
PendingIntervalEventData::ChangeMixCostParams {
|
||||
PendingIntervalEventKind::ChangeMixCostParams {
|
||||
mix_id,
|
||||
new_costs: update.clone()
|
||||
},
|
||||
event.1
|
||||
event.1.kind
|
||||
);
|
||||
|
||||
// execute the event
|
||||
test_helpers::execute_all_pending_events(deps.as_mut(), env);
|
||||
test_helpers::execute_all_pending_events(deps.as_mut(), env.clone());
|
||||
|
||||
// and see if the config has actually been updated
|
||||
let mix = get_mixnode_details_by_id(deps.as_ref().storage, mix_id)
|
||||
@@ -600,8 +626,8 @@ pub mod tests {
|
||||
assert_eq!(mix.rewarding_details.cost_params, update);
|
||||
|
||||
// but we cannot perform any updates whilst the mixnode is already unbonding
|
||||
try_remove_mixnode(deps.as_mut(), info.clone()).unwrap();
|
||||
let res = try_update_mixnode_cost_params(deps.as_mut(), info, update);
|
||||
try_remove_mixnode(deps.as_mut(), env.clone(), info.clone()).unwrap();
|
||||
let res = try_update_mixnode_cost_params(deps.as_mut(), env, info, update);
|
||||
assert_eq!(res, Err(MixnetContractError::MixnodeIsUnbonding { mix_id }))
|
||||
}
|
||||
|
||||
|
||||
@@ -345,7 +345,8 @@ mod tests {
|
||||
total_earned += dist.operator;
|
||||
|
||||
let sender = mock_info(owner, &[]);
|
||||
try_remove_mixnode(test.deps_mut(), sender).unwrap();
|
||||
let env = test.env();
|
||||
try_remove_mixnode(test.deps_mut(), env, sender).unwrap();
|
||||
|
||||
let res = query_pending_operator_reward(test.deps(), owner.into()).unwrap();
|
||||
let res2 = query_pending_mixnode_operator_reward(test.deps(), mix_id).unwrap();
|
||||
@@ -371,7 +372,8 @@ mod tests {
|
||||
test.reward_with_distribution(mix_id, test_helpers::performance(100.0));
|
||||
|
||||
let sender = mock_info(owner, &[]);
|
||||
try_remove_mixnode(test.deps_mut(), sender).unwrap();
|
||||
let env = test.env();
|
||||
try_remove_mixnode(test.deps_mut(), env, sender).unwrap();
|
||||
test.execute_all_pending_events();
|
||||
|
||||
let res = query_pending_operator_reward(test.deps(), owner.into()).unwrap();
|
||||
@@ -493,7 +495,8 @@ mod tests {
|
||||
total_earned += dist.delegates;
|
||||
|
||||
let sender = mock_info("mix-owner", &[]);
|
||||
try_remove_mixnode(test.deps_mut(), sender).unwrap();
|
||||
let env = test.env();
|
||||
try_remove_mixnode(test.deps_mut(), env, sender).unwrap();
|
||||
|
||||
let res =
|
||||
query_pending_delegator_reward(test.deps(), owner.into(), mix_id, None).unwrap();
|
||||
@@ -522,7 +525,8 @@ mod tests {
|
||||
total_earned += dist.delegates;
|
||||
|
||||
let sender = mock_info("mix-owner", &[]);
|
||||
try_remove_mixnode(test.deps_mut(), sender).unwrap();
|
||||
let env = test.env();
|
||||
try_remove_mixnode(test.deps_mut(), env, sender).unwrap();
|
||||
test.execute_all_pending_events();
|
||||
|
||||
let res =
|
||||
@@ -657,7 +661,8 @@ mod tests {
|
||||
test.reward_with_distribution(mix_id, test_helpers::performance(100.0));
|
||||
|
||||
let sender = mock_info(owner, &[]);
|
||||
try_remove_mixnode(test.deps_mut(), sender).unwrap();
|
||||
let env = test.env();
|
||||
try_remove_mixnode(test.deps_mut(), env, sender).unwrap();
|
||||
|
||||
let res = query_estimated_current_epoch_operator_reward(
|
||||
test.deps(),
|
||||
@@ -682,7 +687,8 @@ mod tests {
|
||||
test.reward_with_distribution(mix_id, test_helpers::performance(100.0));
|
||||
|
||||
let sender = mock_info(owner, &[]);
|
||||
try_remove_mixnode(test.deps_mut(), sender).unwrap();
|
||||
let env = test.env();
|
||||
try_remove_mixnode(test.deps_mut(), env, sender).unwrap();
|
||||
test.execute_all_pending_events();
|
||||
|
||||
let res = query_estimated_current_epoch_operator_reward(
|
||||
@@ -833,7 +839,8 @@ mod tests {
|
||||
test.reward_with_distribution(mix_id, test_helpers::performance(100.0));
|
||||
|
||||
let sender = mock_info("mix-owner", &[]);
|
||||
try_remove_mixnode(test.deps_mut(), sender).unwrap();
|
||||
let env = test.env();
|
||||
try_remove_mixnode(test.deps_mut(), env, sender).unwrap();
|
||||
|
||||
let res = query_estimated_current_epoch_delegator_reward(
|
||||
test.deps(),
|
||||
@@ -862,7 +869,8 @@ mod tests {
|
||||
test.reward_with_distribution(mix_id, test_helpers::performance(100.0));
|
||||
|
||||
let sender = mock_info("mix-owner", &[]);
|
||||
try_remove_mixnode(test.deps_mut(), sender).unwrap();
|
||||
let env = test.env();
|
||||
try_remove_mixnode(test.deps_mut(), env, sender).unwrap();
|
||||
test.execute_all_pending_events();
|
||||
|
||||
let res = query_estimated_current_epoch_delegator_reward(
|
||||
|
||||
@@ -22,7 +22,7 @@ use mixnet_contract_common::events::{
|
||||
new_withdraw_delegator_reward_event, new_withdraw_operator_reward_event,
|
||||
new_zero_uptime_mix_operator_rewarding_event,
|
||||
};
|
||||
use mixnet_contract_common::pending_events::{PendingEpochEventData, PendingIntervalEventData};
|
||||
use mixnet_contract_common::pending_events::{PendingEpochEventKind, PendingIntervalEventKind};
|
||||
use mixnet_contract_common::reward_params::{
|
||||
IntervalRewardingParamsUpdate, NodeRewardParams, Performance,
|
||||
};
|
||||
@@ -288,13 +288,16 @@ pub(crate) fn try_update_active_set_size(
|
||||
if force_immediately || interval.is_current_epoch_over(&env) {
|
||||
rewarding_params.try_change_active_set_size(active_set_size)?;
|
||||
storage::REWARDING_PARAMS.save(deps.storage, &rewarding_params)?;
|
||||
Ok(Response::new().add_event(new_active_set_update_event(active_set_size)))
|
||||
Ok(Response::new().add_event(new_active_set_update_event(
|
||||
env.block.height,
|
||||
active_set_size,
|
||||
)))
|
||||
} else {
|
||||
// push the epoch event
|
||||
let epoch_event = PendingEpochEventData::UpdateActiveSetSize {
|
||||
let epoch_event = PendingEpochEventKind::UpdateActiveSetSize {
|
||||
new_size: active_set_size,
|
||||
};
|
||||
push_new_epoch_event(deps.storage, &epoch_event)?;
|
||||
push_new_epoch_event(deps.storage, &env, epoch_event)?;
|
||||
let time_left = interval.secs_until_current_interval_end(&env);
|
||||
Ok(
|
||||
Response::new().add_event(new_pending_active_set_update_event(
|
||||
@@ -324,15 +327,16 @@ pub(crate) fn try_update_rewarding_params(
|
||||
rewarding_params.try_apply_updates(updated_params, interval.epochs_in_interval())?;
|
||||
storage::REWARDING_PARAMS.save(deps.storage, &rewarding_params)?;
|
||||
Ok(Response::new().add_event(new_rewarding_params_update_event(
|
||||
env.block.height,
|
||||
updated_params,
|
||||
rewarding_params.interval,
|
||||
)))
|
||||
} else {
|
||||
// push the interval event
|
||||
let interval_event = PendingIntervalEventData::UpdateRewardingParams {
|
||||
let interval_event = PendingIntervalEventKind::UpdateRewardingParams {
|
||||
update: updated_params,
|
||||
};
|
||||
push_new_interval_event(deps.storage, &interval_event)?;
|
||||
push_new_interval_event(deps.storage, &env, interval_event)?;
|
||||
let time_left = interval.secs_until_current_interval_end(&env);
|
||||
Ok(
|
||||
Response::new().add_event(new_pending_rewarding_params_update_event(
|
||||
@@ -358,7 +362,8 @@ pub mod tests {
|
||||
use cosmwasm_std::{Decimal, Uint128};
|
||||
use mixnet_contract_common::events::{
|
||||
MixnetEventType, BOND_NOT_FOUND_VALUE, DELEGATES_REWARD_KEY, NO_REWARD_REASON_KEY,
|
||||
OPERATOR_REWARD_KEY, PRIOR_DELEGATES_KEY, PRIOR_UNIT_REWARD, ZERO_PERFORMANCE_VALUE,
|
||||
OPERATOR_REWARD_KEY, PRIOR_DELEGATES_KEY, PRIOR_UNIT_REWARD_KEY,
|
||||
ZERO_PERFORMANCE_VALUE,
|
||||
};
|
||||
use mixnet_contract_common::helpers::compare_decimals;
|
||||
use mixnet_contract_common::RewardedSetNodeStatus;
|
||||
@@ -418,9 +423,9 @@ pub mod tests {
|
||||
&rewarding_details,
|
||||
)
|
||||
.unwrap();
|
||||
pending_events::unbond_mixnode(test.deps_mut(), &env, mix_id_unbonded).unwrap();
|
||||
pending_events::unbond_mixnode(test.deps_mut(), &env, 123, mix_id_unbonded).unwrap();
|
||||
|
||||
pending_events::unbond_mixnode(test.deps_mut(), &env, mix_id_unbonded_leftover)
|
||||
pending_events::unbond_mixnode(test.deps_mut(), &env, 123, mix_id_unbonded_leftover)
|
||||
.unwrap();
|
||||
|
||||
let env = test.env();
|
||||
@@ -841,7 +846,7 @@ pub mod tests {
|
||||
|
||||
let prior_unit_reward: Decimal = find_attribute(
|
||||
Some(MixnetEventType::MixnodeRewarding),
|
||||
PRIOR_UNIT_REWARD,
|
||||
PRIOR_UNIT_REWARD_KEY,
|
||||
&res1,
|
||||
)
|
||||
.parse()
|
||||
@@ -903,7 +908,7 @@ pub mod tests {
|
||||
|
||||
let prior_unit_reward: Decimal = find_attribute(
|
||||
Some(MixnetEventType::MixnodeRewarding),
|
||||
PRIOR_UNIT_REWARD,
|
||||
PRIOR_UNIT_REWARD_KEY,
|
||||
&res2,
|
||||
)
|
||||
.parse()
|
||||
@@ -981,7 +986,7 @@ pub mod tests {
|
||||
|
||||
let prior_unit_reward: Decimal = find_attribute(
|
||||
Some(MixnetEventType::MixnodeRewarding),
|
||||
PRIOR_UNIT_REWARD,
|
||||
PRIOR_UNIT_REWARD_KEY,
|
||||
&res1,
|
||||
)
|
||||
.parse()
|
||||
@@ -1050,7 +1055,7 @@ pub mod tests {
|
||||
|
||||
let prior_unit_reward: Decimal = find_attribute(
|
||||
Some(MixnetEventType::MixnodeRewarding),
|
||||
PRIOR_UNIT_REWARD,
|
||||
PRIOR_UNIT_REWARD_KEY,
|
||||
&res2,
|
||||
)
|
||||
.parse()
|
||||
@@ -1223,7 +1228,7 @@ pub mod tests {
|
||||
.unwrap();
|
||||
|
||||
let env = test.env();
|
||||
pending_events::unbond_mixnode(test.deps_mut(), &env, mix_id_unbonded_leftover)
|
||||
pending_events::unbond_mixnode(test.deps_mut(), &env, 123, mix_id_unbonded_leftover)
|
||||
.unwrap();
|
||||
|
||||
let res =
|
||||
@@ -1505,7 +1510,7 @@ pub mod tests {
|
||||
.unwrap();
|
||||
|
||||
let env = test.env();
|
||||
pending_events::unbond_mixnode(test.deps_mut(), &env, mix_id_unbonded_leftover)
|
||||
pending_events::unbond_mixnode(test.deps_mut(), &env, 123, mix_id_unbonded_leftover)
|
||||
.unwrap();
|
||||
|
||||
let res = try_withdraw_operator_reward(test.deps_mut(), sender1);
|
||||
@@ -1675,7 +1680,7 @@ pub mod tests {
|
||||
// make sure it's actually saved to pending events
|
||||
let events = test.pending_epoch_events();
|
||||
assert!(
|
||||
matches!(events[0], PendingEpochEventData::UpdateActiveSetSize { new_size } if new_size == 42)
|
||||
matches!(events[0].kind, PendingEpochEventKind::UpdateActiveSetSize { new_size } if new_size == 42)
|
||||
);
|
||||
|
||||
test.execute_all_pending_events();
|
||||
@@ -1830,7 +1835,7 @@ pub mod tests {
|
||||
// make sure it's actually saved to pending events
|
||||
let events = test.pending_interval_events();
|
||||
assert!(
|
||||
matches!(events[0],PendingIntervalEventData::UpdateRewardingParams { update } if update.rewarded_set_size == Some(123))
|
||||
matches!(events[0].kind,PendingIntervalEventKind::UpdateRewardingParams { update } if update.rewarded_set_size == Some(123))
|
||||
);
|
||||
|
||||
test.execute_all_pending_events();
|
||||
|
||||
@@ -216,13 +216,19 @@ pub mod test_helpers {
|
||||
.load(self.deps().storage, mix_id)
|
||||
.unwrap();
|
||||
|
||||
try_remove_mixnode(self.deps_mut(), mock_info(bond_details.owner.as_str(), &[]))
|
||||
.unwrap();
|
||||
let env = self.env();
|
||||
try_remove_mixnode(
|
||||
self.deps_mut(),
|
||||
env,
|
||||
mock_info(bond_details.owner.as_str(), &[]),
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
pub fn immediately_unbond_mixnode(&mut self, mix_id: MixId) {
|
||||
let env = self.env();
|
||||
pending_events::unbond_mixnode(self.deps_mut(), &env, mix_id).unwrap();
|
||||
pending_events::unbond_mixnode(self.deps_mut(), &env, env.block.height, mix_id)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
pub fn add_immediate_delegation(
|
||||
@@ -240,6 +246,7 @@ pub mod test_helpers {
|
||||
pending_events::delegate(
|
||||
self.deps_mut(),
|
||||
&env,
|
||||
env.block.height,
|
||||
Addr::unchecked(delegator),
|
||||
target,
|
||||
amount,
|
||||
@@ -264,6 +271,7 @@ pub mod test_helpers {
|
||||
pending_events::delegate(
|
||||
self.deps_mut(),
|
||||
&env,
|
||||
env.block.height,
|
||||
Addr::unchecked(delegator),
|
||||
target,
|
||||
amount,
|
||||
@@ -284,12 +292,20 @@ pub mod test_helpers {
|
||||
denom,
|
||||
amount: amount.into(),
|
||||
};
|
||||
delegate(self.deps_mut(), delegator, vec![amount], target)
|
||||
let env = self.env();
|
||||
delegate(self.deps_mut(), env, delegator, vec![amount], target)
|
||||
}
|
||||
|
||||
pub fn remove_immediate_delegation(&mut self, delegator: &str, target: MixId) {
|
||||
pending_events::undelegate(self.deps_mut(), Addr::unchecked(delegator), target, None)
|
||||
.unwrap();
|
||||
let height = self.env.block.height;
|
||||
pending_events::undelegate(
|
||||
self.deps_mut(),
|
||||
height,
|
||||
Addr::unchecked(delegator),
|
||||
target,
|
||||
None,
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
pub fn skip_to_next_epoch_end(&mut self) {
|
||||
@@ -556,6 +572,7 @@ pub mod test_helpers {
|
||||
pending_events::delegate(
|
||||
deps.branch(),
|
||||
&env,
|
||||
env.block.height,
|
||||
Addr::unchecked(&format!("owner{}", i)),
|
||||
mix_id,
|
||||
tests::fixtures::good_mixnode_pledge().pop().unwrap(),
|
||||
@@ -775,9 +792,9 @@ pub mod test_helpers {
|
||||
deps
|
||||
}
|
||||
|
||||
pub fn delegate(deps: DepsMut<'_>, sender: &str, stake: Vec<Coin>, mix_id: MixId) {
|
||||
pub fn delegate(deps: DepsMut<'_>, env: Env, sender: &str, stake: Vec<Coin>, mix_id: MixId) {
|
||||
let info = mock_info(sender, &stake);
|
||||
try_delegate_to_mixnode(deps, info, mix_id).unwrap();
|
||||
try_delegate_to_mixnode(deps, env, info, mix_id).unwrap();
|
||||
}
|
||||
|
||||
pub(crate) fn read_delegation(
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { PendingEpochEventData } from './PendingEpochEventData';
|
||||
import type {PendingEpochEventData} from "./PendingEpochEventData";
|
||||
|
||||
export interface PendingEpochEvent {
|
||||
id: number;
|
||||
event: PendingEpochEventData;
|
||||
id: number,
|
||||
created_at: bigint,
|
||||
event: PendingEpochEventData,
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { PendingIntervalEventData } from './PendingIntervalEventData';
|
||||
import type {PendingIntervalEventData} from "./PendingIntervalEventData";
|
||||
|
||||
export interface PendingIntervalEvent {
|
||||
id: number;
|
||||
event: PendingIntervalEventData;
|
||||
id: number,
|
||||
created_at: bigint,
|
||||
event: PendingIntervalEventData,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user