From f1624e658ebe036a4a0e36c1ca0241eb07e8436f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Mon, 24 Oct 2022 09:30:51 +0100 Subject: [PATCH] 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 --- .../delegators/query_for_delegations.rs | 8 +- .../mixnet-contract/src/delegation.rs | 2 - .../mixnet-contract/src/events.rs | 54 +++++--- .../mixnet-contract/src/lib.rs | 3 +- .../mixnet-contract/src/mixnode.rs | 8 -- .../mixnet-contract/src/pending_events.rs | 36 ++++- .../mixnet-contract/src/types.rs | 1 + common/types/src/pending_events.rs | 35 +++-- contracts/mixnet/src/contract.rs | 20 +-- contracts/mixnet/src/delegations/queries.rs | 2 + .../mixnet/src/delegations/transactions.rs | 125 +++++++++++++----- contracts/mixnet/src/gateways/transactions.rs | 2 +- contracts/mixnet/src/interval/helpers.rs | 6 +- .../mixnet/src/interval/pending_events.rs | 123 +++++++++++------ contracts/mixnet/src/interval/queries.rs | 14 +- contracts/mixnet/src/interval/storage.rs | 20 ++- contracts/mixnet/src/interval/transactions.rs | 113 ++++++++++------ contracts/mixnet/src/mixnodes/queries.rs | 4 +- contracts/mixnet/src/mixnodes/transactions.rs | 74 +++++++---- contracts/mixnet/src/rewards/queries.rs | 24 ++-- contracts/mixnet/src/rewards/transactions.rs | 39 +++--- contracts/mixnet/src/support/tests/mod.rs | 33 +++-- .../types/src/types/rust/PendingEpochEvent.ts | 7 +- .../src/types/rust/PendingIntervalEvent.ts | 7 +- 24 files changed, 501 insertions(+), 259 deletions(-) diff --git a/common/commands/src/validator/mixnet/delegators/query_for_delegations.rs b/common/commands/src/validator/mixnet/delegators/query_for_delegations.rs index 52d43ec553..d816e65a0c 100644 --- a/common/commands/src/validator/mixnet/delegators/query_for_delegations.rs +++ b/common/commands/src/validator/mixnet/delegators/query_for_delegations.rs @@ -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, diff --git a/common/cosmwasm-smart-contracts/mixnet-contract/src/delegation.rs b/common/cosmwasm-smart-contracts/mixnet-contract/src/delegation.rs index 900f1e3c96..ce144ebad9 100644 --- a/common/cosmwasm-smart-contracts/mixnet-contract/src/delegation.rs +++ b/common/cosmwasm-smart-contracts/mixnet-contract/src/delegation.rs @@ -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. diff --git a/common/cosmwasm-smart-contracts/mixnet-contract/src/events.rs b/common/cosmwasm-smart-contracts/mixnet-contract/src/events.rs index 4bcaa66180..bba85e3ccd 100644 --- a/common/cosmwasm-smart-contracts/mixnet-contract/src/events.rs +++ b/common/cosmwasm-smart-contracts/mixnet-contract/src/events.rs @@ -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, 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, mix_id: MixId) -> Event { +pub fn new_undelegation_event( + created_at: BlockHeight, + delegator: &Addr, + proxy: &Option, + 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(), diff --git a/common/cosmwasm-smart-contracts/mixnet-contract/src/lib.rs b/common/cosmwasm-smart-contracts/mixnet-contract/src/lib.rs index d48f6d9c46..200b4c5a00 100644 --- a/common/cosmwasm-smart-contracts/mixnet-contract/src/lib.rs +++ b/common/cosmwasm-smart-contracts/mixnet-contract/src/lib.rs @@ -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::*; diff --git a/common/cosmwasm-smart-contracts/mixnet-contract/src/mixnode.rs b/common/cosmwasm-smart-contracts/mixnet-contract/src/mixnode.rs index f77ca73642..5eb98bcbb3 100644 --- a/common/cosmwasm-smart-contracts/mixnet-contract/src/mixnode.rs +++ b/common/cosmwasm-smart-contracts/mixnet-contract/src/mixnode.rs @@ -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. diff --git a/common/cosmwasm-smart-contracts/mixnet-contract/src/pending_events.rs b/common/cosmwasm-smart-contracts/mixnet-contract/src/pending_events.rs index 59a2ad9777..fce8bd8cf0 100644 --- a/common/cosmwasm-smart-contracts/mixnet-contract/src/pending_events.rs +++ b/common/cosmwasm-smart-contracts/mixnet-contract/src/pending_events.rs @@ -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 { diff --git a/common/cosmwasm-smart-contracts/mixnet-contract/src/types.rs b/common/cosmwasm-smart-contracts/mixnet-contract/src/types.rs index f183986cd5..7d6e8f2d0d 100644 --- a/common/cosmwasm-smart-contracts/mixnet-contract/src/types.rs +++ b/common/cosmwasm-smart-contracts/mixnet-contract/src/types.rs @@ -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; diff --git a/common/types/src/pending_events.rs b/common/types/src/pending_events.rs index 9e66f58bfd..afe5a54d9e 100644 --- a/common/types/src/pending_events.rs +++ b/common/types/src/pending_events.rs @@ -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 { 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 { 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 { 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 { 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 { diff --git a/contracts/mixnet/src/contract.rs b/contracts/mixnet/src/contract.rs index 929dd196c2..1e91323c6c 100644 --- a/contracts/mixnet/src/contract.rs +++ b/contracts/mixnet/src/contract.rs @@ -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, ) } diff --git a/contracts/mixnet/src/delegations/queries.rs b/contracts/mixnet/src/delegations/queries.rs index 855a2d732b..ff913c030b 100644 --- a/contracts/mixnet/src/delegations/queries.rs +++ b/contracts/mixnet/src/delegations/queries.rs @@ -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(), diff --git a/contracts/mixnet/src/delegations/transactions.rs b/contracts/mixnet/src/delegations/transactions.rs index b2f3df4b20..271a2c190d 100644 --- a/contracts/mixnet/src/delegations/transactions.rs +++ b/contracts/mixnet/src/delegations/transactions.rs @@ -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 { - _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 { 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, @@ -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 { - _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 { 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, @@ -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, ); diff --git a/contracts/mixnet/src/gateways/transactions.rs b/contracts/mixnet/src/gateways/transactions.rs index 3b28394e46..55973f7589 100644 --- a/contracts/mixnet/src/gateways/transactions.rs +++ b/contracts/mixnet/src/gateways/transactions.rs @@ -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()); diff --git a/contracts/mixnet/src/interval/helpers.rs b/contracts/mixnet/src/interval/helpers.rs index 5187943154..dd45c7511a 100644 --- a/contracts/mixnet/src/interval/helpers.rs +++ b/contracts/mixnet/src/interval/helpers.rs @@ -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(), diff --git a/contracts/mixnet/src/interval/pending_events.rs b/contracts/mixnet/src/interval/pending_events.rs index f7cac45891..84a5be1163 100644 --- a/contracts/mixnet/src/interval/pending_events.rs +++ b/contracts/mixnet/src/interval/pending_events.rs @@ -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, @@ -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 { // 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 { // 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 { // 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 { @@ -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 { // 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 { @@ -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 { // 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, ) diff --git a/contracts/mixnet/src/interval/queries.rs b/contracts/mixnet/src/interval/queries.rs index b894e887b5..a0fe28ed28 100644 --- a/contracts/mixnet/src/interval/queries.rs +++ b/contracts/mixnet/src/interval/queries.rs @@ -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] diff --git a/contracts/mixnet/src/interval/storage.rs b/contracts/mixnet/src/interval/storage.rs index 50924f9186..282876f5f8 100644 --- a/contracts/mixnet/src/interval/storage.rs +++ b/contracts/mixnet/src/interval/storage.rs @@ -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( diff --git a/contracts/mixnet/src/interval/transactions.rs b/contracts/mixnet/src/interval/transactions.rs index fb0fc51887..705f36804a 100644 --- a/contracts/mixnet/src/interval/transactions.rs +++ b/contracts/mixnet/src/interval/transactions.rs @@ -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> = 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> = 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(); diff --git a/contracts/mixnet/src/mixnodes/queries.rs b/contracts/mixnet/src/mixnodes/queries.rs index ee28a2cfd0..5411b108ff 100644 --- a/contracts/mixnet/src/mixnodes/queries.rs +++ b/contracts/mixnet/src/mixnodes/queries.rs @@ -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); diff --git a/contracts/mixnet/src/mixnodes/transactions.rs b/contracts/mixnet/src/mixnodes/transactions.rs index 8d51705f6b..0a1e816ffd 100644 --- a/contracts/mixnet/src/mixnodes/transactions.rs +++ b/contracts/mixnet/src/mixnodes/transactions.rs @@ -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 { 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 { - _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, ) -> Result { @@ -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 { 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 { 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, @@ -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 })) } diff --git a/contracts/mixnet/src/rewards/queries.rs b/contracts/mixnet/src/rewards/queries.rs index 4b28b799ed..2b969c410b 100644 --- a/contracts/mixnet/src/rewards/queries.rs +++ b/contracts/mixnet/src/rewards/queries.rs @@ -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( diff --git a/contracts/mixnet/src/rewards/transactions.rs b/contracts/mixnet/src/rewards/transactions.rs index b540375cd7..b56686651f 100644 --- a/contracts/mixnet/src/rewards/transactions.rs +++ b/contracts/mixnet/src/rewards/transactions.rs @@ -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(); diff --git a/contracts/mixnet/src/support/tests/mod.rs b/contracts/mixnet/src/support/tests/mod.rs index ebd1024bf0..07b89671cd 100644 --- a/contracts/mixnet/src/support/tests/mod.rs +++ b/contracts/mixnet/src/support/tests/mod.rs @@ -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, mix_id: MixId) { + pub fn delegate(deps: DepsMut<'_>, env: Env, sender: &str, stake: Vec, 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( diff --git a/ts-packages/types/src/types/rust/PendingEpochEvent.ts b/ts-packages/types/src/types/rust/PendingEpochEvent.ts index 7c8125b70d..e775e935c0 100644 --- a/ts-packages/types/src/types/rust/PendingEpochEvent.ts +++ b/ts-packages/types/src/types/rust/PendingEpochEvent.ts @@ -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, } diff --git a/ts-packages/types/src/types/rust/PendingIntervalEvent.ts b/ts-packages/types/src/types/rust/PendingIntervalEvent.ts index cc5ed2d674..1c72712ef5 100644 --- a/ts-packages/types/src/types/rust/PendingIntervalEvent.ts +++ b/ts-packages/types/src/types/rust/PendingIntervalEvent.ts @@ -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, }