diff --git a/clients/client-core/src/client/topology_control.rs b/clients/client-core/src/client/topology_control.rs index 0863e1e867..f8a9949776 100644 --- a/clients/client-core/src/client/topology_control.rs +++ b/clients/client-core/src/client/topology_control.rs @@ -257,7 +257,7 @@ impl TopologyRefresher { Ok(mixes) => mixes, }; - let gateways = match self.validator_client.get_cached_active_gateways().await { + let gateways = match self.validator_client.get_cached_gateways().await { Err(err) => { error!("failed to get network gateways - {}", err); return None; diff --git a/clients/webassembly/src/client/mod.rs b/clients/webassembly/src/client/mod.rs index 1187eb0ad2..ed1397dc43 100644 --- a/clients/webassembly/src/client/mod.rs +++ b/clients/webassembly/src/client/mod.rs @@ -279,7 +279,7 @@ impl NymClient { Ok(mixes) => mixes, }; - let gateways = match validator_client.get_cached_active_gateways().await { + let gateways = match validator_client.get_cached_gateways().await { Err(err) => panic!("{}", err), Ok(gateways) => gateways, }; diff --git a/common/client-libs/validator-client/src/client.rs b/common/client-libs/validator-client/src/client.rs index 48535ba7d8..0e2533b37d 100644 --- a/common/client-libs/validator-client/src/client.rs +++ b/common/client-libs/validator-client/src/client.rs @@ -24,7 +24,6 @@ pub struct Config { mixnode_page_limit: Option, gateway_page_limit: Option, mixnode_delegations_page_limit: Option, - gateway_delegations_page_limit: Option, } #[cfg(feature = "nymd-client")] @@ -41,7 +40,6 @@ impl Config { mixnode_page_limit: None, gateway_page_limit: None, mixnode_delegations_page_limit: None, - gateway_delegations_page_limit: None, } } @@ -59,11 +57,6 @@ impl Config { self.mixnode_delegations_page_limit = limit; self } - - pub fn with_gateway_delegations_page_limit(mut self, limit: Option) -> Config { - self.gateway_delegations_page_limit = limit; - self - } } #[cfg(feature = "nymd-client")] @@ -74,7 +67,6 @@ pub struct Client { mixnode_page_limit: Option, gateway_page_limit: Option, mixnode_delegations_page_limit: Option, - gateway_delegations_page_limit: Option, // ideally they would have been read-only, but unfortunately rust doesn't have such features pub validator_api: validator_api::Client, @@ -100,7 +92,6 @@ impl Client { mixnode_page_limit: config.mixnode_page_limit, gateway_page_limit: config.gateway_page_limit, mixnode_delegations_page_limit: config.mixnode_delegations_page_limit, - gateway_delegations_page_limit: config.gateway_delegations_page_limit, validator_api: validator_api_client, nymd: nymd_client, }) @@ -136,7 +127,6 @@ impl Client { mixnode_page_limit: config.mixnode_page_limit, gateway_page_limit: config.gateway_page_limit, mixnode_delegations_page_limit: config.mixnode_delegations_page_limit, - gateway_delegations_page_limit: config.gateway_delegations_page_limit, validator_api: validator_api_client, nymd: nymd_client, }) @@ -339,116 +329,6 @@ impl Client { Ok(delegations) } - pub async fn get_all_nymd_single_gateway_delegations( - &self, - identity: mixnet_contract::IdentityKey, - ) -> Result, ValidatorClientError> - where - C: CosmWasmClient + Sync, - { - let mut delegations = Vec::new(); - let mut start_after = None; - loop { - let mut paged_response = self - .nymd - .get_gateway_delegations( - identity.clone(), - start_after.take(), - self.gateway_delegations_page_limit, - ) - .await?; - delegations.append(&mut paged_response.delegations); - - if let Some(start_after_res) = paged_response.start_next_after { - start_after = Some(start_after_res) - } else { - break; - } - } - - Ok(delegations) - } - - pub async fn get_all_nymd_gateway_delegations( - &self, - ) -> Result>, ValidatorClientError> - where - C: CosmWasmClient + Sync, - { - let mut delegations = Vec::new(); - let mut start_after = None; - loop { - let mut paged_response = self - .nymd - .get_all_gateway_delegations( - start_after.take(), - self.gateway_delegations_page_limit, - ) - .await?; - delegations.append(&mut paged_response.delegations); - - if let Some(start_after_res) = paged_response.start_next_after { - start_after = Some(start_after_res) - } else { - break; - } - } - - Ok(delegations) - } - - pub async fn get_all_nymd_reverse_gateway_delegations( - &self, - delegation_owner: &cosmrs::AccountId, - ) -> Result, ValidatorClientError> - where - C: CosmWasmClient + Sync, - { - let mut delegations = Vec::new(); - let mut start_after = None; - loop { - let mut paged_response = self - .nymd - .get_reverse_gateway_delegations_paged( - mixnet_contract::Addr::unchecked(delegation_owner.as_ref()), - start_after.take(), - self.mixnode_delegations_page_limit, - ) - .await?; - delegations.append(&mut paged_response.delegated_nodes); - - if let Some(start_after_res) = paged_response.start_next_after { - start_after = Some(start_after_res) - } else { - break; - } - } - - Ok(delegations) - } - - pub async fn get_all_nymd_gateway_delegations_of_owner( - &self, - delegation_owner: &cosmrs::AccountId, - ) -> Result, ValidatorClientError> - where - C: CosmWasmClient + Sync, - { - let mut delegations = Vec::new(); - for node_identity in self - .get_all_nymd_reverse_gateway_delegations(delegation_owner) - .await? - { - let delegation = self - .nymd - .get_gateway_delegation(node_identity, delegation_owner) - .await?; - delegations.push(delegation); - } - - Ok(delegations) - } - pub async fn blind_sign( &self, request_body: &BlindSignRequestBody, @@ -488,12 +368,6 @@ impl ApiClient { Ok(self.validator_api.get_active_mixnodes().await?) } - pub async fn get_cached_active_gateways( - &self, - ) -> Result, ValidatorClientError> { - Ok(self.validator_api.get_active_gateways().await?) - } - pub async fn get_cached_mixnodes(&self) -> Result, ValidatorClientError> { Ok(self.validator_api.get_mixnodes().await?) } diff --git a/common/client-libs/validator-client/src/nymd/mod.rs b/common/client-libs/validator-client/src/nymd/mod.rs index 2ec670fb6e..54477ca013 100644 --- a/common/client-libs/validator-client/src/nymd/mod.rs +++ b/common/client-libs/validator-client/src/nymd/mod.rs @@ -15,8 +15,7 @@ use cosmwasm_std::Coin; use mixnet_contract::{ Addr, Delegation, ExecuteMsg, Gateway, GatewayOwnershipResponse, IdentityKey, LayerDistribution, MixNode, MixOwnershipResponse, PagedAllDelegationsResponse, - PagedGatewayDelegationsResponse, PagedGatewayResponse, PagedMixDelegationsResponse, - PagedMixnodeResponse, PagedReverseGatewayDelegationsResponse, + PagedGatewayResponse, PagedMixDelegationsResponse, PagedMixnodeResponse, PagedReverseMixDelegationsResponse, QueryMsg, RawDelegationData, StateParams, }; use serde::Serialize; @@ -354,82 +353,6 @@ impl NymdClient { .await } - /// Gets list of all delegations towards particular gateway on particular page. - pub async fn get_gateway_delegations( - &self, - gateway_identity: IdentityKey, - start_after: Option, - page_limit: Option, - ) -> Result - where - C: CosmWasmClient + Sync, - { - let request = QueryMsg::GetGatewayDelegations { - gateway_identity, - start_after, - limit: page_limit, - }; - self.client - .query_contract_smart(self.contract_address()?, &request) - .await - } - - /// Gets list of all gateway delegations on particular page. - pub async fn get_all_gateway_delegations( - &self, - start_after: Option>, - page_limit: Option, - ) -> Result, NymdError> - where - C: CosmWasmClient + Sync, - { - let request = QueryMsg::GetAllGatewayDelegations { - start_after, - limit: page_limit, - }; - self.client - .query_contract_smart(self.contract_address()?, &request) - .await - } - - /// Gets list of all the gateways on which a particular address delegated. - pub async fn get_reverse_gateway_delegations_paged( - &self, - delegation_owner: Addr, - start_after: Option, - page_limit: Option, - ) -> Result - where - C: CosmWasmClient + Sync, - { - let request = QueryMsg::GetReverseGatewayDelegations { - delegation_owner, - start_after, - limit: page_limit, - }; - self.client - .query_contract_smart(self.contract_address()?, &request) - .await - } - - /// Checks value of delegation of given client towards particular gateway. - pub async fn get_gateway_delegation( - &self, - gateway_identity: IdentityKey, - delegator: &AccountId, - ) -> Result - where - C: CosmWasmClient + Sync, - { - let request = QueryMsg::GetGatewayDelegation { - gateway_identity, - address: Addr::unchecked(delegator.as_ref()), - }; - self.client - .query_contract_smart(self.contract_address()?, &request) - .await - } - /// Send funds from one address to another pub async fn send( &self, @@ -698,57 +621,6 @@ impl NymdClient { .await } - /// Delegates specified amount of stake to particular gateway. - pub async fn delegate_to_gateway( - &self, - gateway_identity: &str, - amount: &Coin, - ) -> Result - where - C: SigningCosmWasmClient + Sync, - { - let fee = self.get_fee(Operation::DelegateToGateway); - - let req = ExecuteMsg::DelegateToGateway { - gateway_identity: gateway_identity.to_string(), - }; - self.client - .execute( - self.address(), - self.contract_address()?, - &req, - fee, - "Delegating to gateway from rust!", - vec![cosmwasm_coin_ptr_to_cosmos_coin(amount)], - ) - .await - } - - /// Removes stake delegation from a particular gateway. - pub async fn remove_gateway_delegation( - &self, - gateway_identity: &str, - ) -> Result - where - C: SigningCosmWasmClient + Sync, - { - let fee = self.get_fee(Operation::UndelegateFromGateway); - - let req = ExecuteMsg::UndelegateFromGateway { - gateway_identity: gateway_identity.to_string(), - }; - self.client - .execute( - self.address(), - self.contract_address()?, - &req, - fee, - "Removing gateway delegation from rust!", - Vec::new(), - ) - .await - } - pub async fn update_state_params( &self, new_params: StateParams, diff --git a/common/client-libs/validator-client/src/validator_api/mod.rs b/common/client-libs/validator-client/src/validator_api/mod.rs index dcc448d7d9..8b993a5b7e 100644 --- a/common/client-libs/validator-client/src/validator_api/mod.rs +++ b/common/client-libs/validator-client/src/validator_api/mod.rs @@ -73,11 +73,6 @@ impl Client { .await } - pub async fn get_active_gateways(&self) -> Result, ValidatorAPIError> { - self.query_validator_api(&[routes::API_VERSION, routes::GATEWAYS, routes::ACTIVE]) - .await - } - pub async fn blind_sign( &self, request_body: &BlindSignRequestBody, diff --git a/common/mixnet-contract/src/delegation.rs b/common/mixnet-contract/src/delegation.rs index 65fc4c1dd2..87d6e63a51 100644 --- a/common/mixnet-contract/src/delegation.rs +++ b/common/mixnet-contract/src/delegation.rs @@ -120,48 +120,6 @@ impl PagedReverseMixDelegationsResponse { } } -#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)] -pub struct PagedGatewayDelegationsResponse { - pub node_identity: IdentityKey, - pub delegations: Vec, - pub start_next_after: Option, -} - -impl PagedGatewayDelegationsResponse { - pub fn new( - node_identity: IdentityKey, - delegations: Vec, - start_next_after: Option, - ) -> Self { - PagedGatewayDelegationsResponse { - node_identity, - delegations, - start_next_after, - } - } -} - -#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)] -pub struct PagedReverseGatewayDelegationsResponse { - pub delegation_owner: Addr, - pub delegated_nodes: Vec, - pub start_next_after: Option, -} - -impl PagedReverseGatewayDelegationsResponse { - pub fn new( - delegation_owner: Addr, - delegated_nodes: Vec, - start_next_after: Option, - ) -> Self { - PagedReverseGatewayDelegationsResponse { - delegation_owner, - delegated_nodes, - start_next_after, - } - } -} - #[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)] pub struct PagedAllDelegationsResponse { pub delegations: Vec>, diff --git a/common/mixnet-contract/src/gateway.rs b/common/mixnet-contract/src/gateway.rs index 34e29fbcd8..25c9fe0bab 100644 --- a/common/mixnet-contract/src/gateway.rs +++ b/common/mixnet-contract/src/gateway.rs @@ -2,7 +2,7 @@ #![allow(clippy::field_reassign_with_default)] use crate::{IdentityKey, SphinxKey}; -use cosmwasm_std::{coin, Addr, Coin}; +use cosmwasm_std::{Addr, Coin}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use std::cmp::Ordering; @@ -24,7 +24,6 @@ pub struct Gateway { #[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)] pub struct GatewayBond { pub bond_amount: Coin, - pub total_delegation: Coin, pub owner: Addr, pub block_height: u64, pub gateway: Gateway, @@ -33,7 +32,6 @@ pub struct GatewayBond { impl GatewayBond { pub fn new(bond_amount: Coin, owner: Addr, block_height: u64, gateway: Gateway) -> Self { GatewayBond { - total_delegation: coin(0, &bond_amount.denom), bond_amount, owner, block_height, @@ -61,27 +59,11 @@ impl GatewayBond { impl PartialOrd for GatewayBond { fn partial_cmp(&self, other: &Self) -> Option { // first remove invalid cases - if self.bond_amount.denom != self.total_delegation.denom { - return None; - } - - if other.bond_amount.denom != other.total_delegation.denom { - return None; - } - if self.bond_amount.denom != other.bond_amount.denom { return None; } - // try to order by total bond + delegation - let total_cmp = (self.bond_amount.amount + self.total_delegation.amount) - .partial_cmp(&(self.bond_amount.amount + self.total_delegation.amount))?; - - if total_cmp != Ordering::Equal { - return Some(total_cmp); - } - - // then if those are equal, prefer higher bond over delegation + // try to order by total bond let bond_cmp = self .bond_amount .amount @@ -90,15 +72,6 @@ impl PartialOrd for GatewayBond { return Some(bond_cmp); } - // then look at delegation (I'm not sure we can get here, but better safe than sorry) - let delegation_cmp = self - .total_delegation - .amount - .partial_cmp(&other.total_delegation.amount)?; - if delegation_cmp != Ordering::Equal { - return Some(delegation_cmp); - } - // then check block height let height_cmp = self.block_height.partial_cmp(&other.block_height)?; if height_cmp != Ordering::Equal { @@ -172,20 +145,19 @@ mod tests { #[test] fn gateway_bond_partial_ord() { let _150foos = Coin::new(150, "foo"); + let _140foos = Coin::new(140, "foo"); let _50foos = Coin::new(50, "foo"); let _0foos = Coin::new(0, "foo"); let gate1 = GatewayBond { bond_amount: _150foos.clone(), - total_delegation: _50foos.clone(), owner: Addr::unchecked("foo1"), block_height: 100, gateway: gateway_fixture(), }; let gate2 = GatewayBond { - bond_amount: _150foos.clone(), - total_delegation: _50foos.clone(), + bond_amount: _150foos, owner: Addr::unchecked("foo2"), block_height: 120, gateway: gateway_fixture(), @@ -193,15 +165,13 @@ mod tests { let gate3 = GatewayBond { bond_amount: _50foos, - total_delegation: _150foos.clone(), owner: Addr::unchecked("foo3"), block_height: 120, gateway: gateway_fixture(), }; let gate4 = GatewayBond { - bond_amount: _150foos.clone(), - total_delegation: _0foos.clone(), + bond_amount: _140foos, owner: Addr::unchecked("foo4"), block_height: 120, gateway: gateway_fixture(), @@ -209,21 +179,19 @@ mod tests { let gate5 = GatewayBond { bond_amount: _0foos, - total_delegation: _150foos, owner: Addr::unchecked("foo5"), block_height: 120, gateway: gateway_fixture(), }; // summary: - // gate1: 150bond + 50delegation, foo1, 100 - // gate2: 150bond + 50delegation, foo2, 120 - // gate3: 50bond + 150delegation, foo3, 120 - // gate4: 150bond + 0delegation, foo4, 120 - // gate5: 0bond + 150delegation, foo5, 120 + // gate1: 150bond, foo1, 100 + // gate2: 150bond, foo2, 120 + // gate3: 50bond, foo3, 120 + // gate4: 140bond, foo4, 120 + // gate5: 0bond, foo5, 120 - // highest total bond+delegation is used - // then bond followed by delegation + // highest total bond is used // finally just the rest of the fields // gate1 has higher total than gate4 or gate5 diff --git a/common/mixnet-contract/src/lib.rs b/common/mixnet-contract/src/lib.rs index f835b87ad0..ffecdea57c 100644 --- a/common/mixnet-contract/src/lib.rs +++ b/common/mixnet-contract/src/lib.rs @@ -9,8 +9,7 @@ mod types; pub use cosmwasm_std::{Addr, Coin}; pub use delegation::{ - Delegation, PagedAllDelegationsResponse, PagedGatewayDelegationsResponse, - PagedMixDelegationsResponse, PagedReverseGatewayDelegationsResponse, + Delegation, PagedAllDelegationsResponse, PagedMixDelegationsResponse, PagedReverseMixDelegationsResponse, RawDelegationData, UnpackedDelegation, }; pub use gateway::{Gateway, GatewayBond, GatewayOwnershipResponse, PagedGatewayResponse}; diff --git a/common/mixnet-contract/src/msg.rs b/common/mixnet-contract/src/msg.rs index 15b4193369..dfda40befa 100644 --- a/common/mixnet-contract/src/msg.rs +++ b/common/mixnet-contract/src/msg.rs @@ -31,25 +31,11 @@ pub enum ExecuteMsg { mix_identity: IdentityKey, }, - DelegateToGateway { - gateway_identity: IdentityKey, - }, - - UndelegateFromGateway { - gateway_identity: IdentityKey, - }, - RewardMixnode { identity: IdentityKey, // percentage value in range 0-100 uptime: u32, }, - - RewardGateway { - identity: IdentityKey, - // percentage value in range 0-100 - uptime: u32, - }, } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] @@ -88,24 +74,6 @@ pub enum QueryMsg { mix_identity: IdentityKey, address: Addr, }, - GetGatewayDelegations { - gateway_identity: IdentityKey, - start_after: Option, - limit: Option, - }, - GetAllGatewayDelegations { - start_after: Option>, - limit: Option, - }, - GetReverseGatewayDelegations { - delegation_owner: Addr, - start_after: Option, - limit: Option, - }, - GetGatewayDelegation { - gateway_identity: IdentityKey, - address: Addr, - }, LayerDistribution {}, } diff --git a/common/mixnet-contract/src/types.rs b/common/mixnet-contract/src/types.rs index bc3e3eb24f..b2a16515fe 100644 --- a/common/mixnet-contract/src/types.rs +++ b/common/mixnet-contract/src/types.rs @@ -32,12 +32,10 @@ pub struct StateParams { pub minimum_mixnode_bond: Uint128, // minimum amount a mixnode must bond to get into the system pub minimum_gateway_bond: Uint128, // minimum amount a gateway must bond to get into the system + pub mixnode_bond_reward_rate: Decimal, // annual reward rate, expressed as a decimal like 1.25 - pub gateway_bond_reward_rate: Decimal, // annual reward rate, expressed as a decimal like 1.25 pub mixnode_delegation_reward_rate: Decimal, // annual reward rate, expressed as a decimal like 1.25 - pub gateway_delegation_reward_rate: Decimal, // annual reward rate, expressed as a decimal like 1.25 pub mixnode_active_set_size: u32, - pub gateway_active_set_size: u32, } impl Display for StateParams { @@ -51,30 +49,15 @@ impl Display for StateParams { "mixnode bond reward rate: {}; ", self.mixnode_bond_reward_rate )?; - write!( - f, - "gateway bond reward rate: {}; ", - self.gateway_bond_reward_rate - )?; write!( f, "mixnode delegation reward rate: {}; ", self.mixnode_delegation_reward_rate )?; - write!( - f, - "gateway delegation reward rate: {}; ", - self.gateway_delegation_reward_rate - )?; write!( f, "mixnode active set size: {}", self.mixnode_active_set_size - )?; - write!( - f, - "gateway active set size: {} ]", - self.gateway_active_set_size ) } } diff --git a/common/nymsphinx/src/receiver.rs b/common/nymsphinx/src/receiver.rs index 76c65c1f15..c3e9aebd9d 100644 --- a/common/nymsphinx/src/receiver.rs +++ b/common/nymsphinx/src/receiver.rs @@ -268,7 +268,6 @@ mod message_receiver { vec![gateway::Node { owner: "foomp4".to_string(), stake: 123, - delegation: 456, location: "unknown".to_string(), host: "1.2.3.4".parse().unwrap(), mix_host: "1.2.3.4:1789".parse().unwrap(), diff --git a/common/topology/src/gateway.rs b/common/topology/src/gateway.rs index 45fb7b0dfd..f617089592 100644 --- a/common/topology/src/gateway.rs +++ b/common/topology/src/gateway.rs @@ -72,7 +72,6 @@ pub struct Node { // somebody correct me if I'm wrong, but we should only ever have a single denom of currency // on the network at a type, right? pub stake: u128, - pub delegation: u128, pub location: String, pub host: NetworkAddress, // we're keeping this as separate resolved field since we do not want to be resolving the potential @@ -127,7 +126,6 @@ impl<'a> TryFrom<&'a GatewayBond> for Node { Ok(Node { owner: bond.owner.as_str().to_owned(), stake: bond.bond_amount.amount.into(), - delegation: bond.total_delegation.amount.into(), location: bond.gateway.location.clone(), host, mix_host, diff --git a/contracts/mixnet/src/contract.rs b/contracts/mixnet/src/contract.rs index 8321e1fc3a..4dc9dac8e4 100644 --- a/contracts/mixnet/src/contract.rs +++ b/contracts/mixnet/src/contract.rs @@ -22,18 +22,13 @@ pub const INITIAL_MIXNODE_BOND: Uint128 = Uint128(100_000000); // percentage annual increase. Given starting value of x, we expect to have 1.1x at the end of the year pub const INITIAL_MIXNODE_BOND_REWARD_RATE: u64 = 110; -pub const INITIAL_GATEWAY_BOND_REWARD_RATE: u64 = 110; pub const INITIAL_MIXNODE_DELEGATION_REWARD_RATE: u64 = 110; -pub const INITIAL_GATEWAY_DELEGATION_REWARD_RATE: u64 = 110; pub const INITIAL_MIXNODE_ACTIVE_SET_SIZE: u32 = 100; -pub const INITIAL_GATEWAY_ACTIVE_SET_SIZE: u32 = 20; fn default_initial_state(owner: Addr) -> State { let mixnode_bond_reward_rate = Decimal::percent(INITIAL_MIXNODE_BOND_REWARD_RATE); - let gateway_bond_reward_rate = Decimal::percent(INITIAL_GATEWAY_BOND_REWARD_RATE); let mixnode_delegation_reward_rate = Decimal::percent(INITIAL_MIXNODE_DELEGATION_REWARD_RATE); - let gateway_delegation_reward_rate = Decimal::percent(INITIAL_GATEWAY_DELEGATION_REWARD_RATE); State { owner, @@ -43,28 +38,17 @@ fn default_initial_state(owner: Addr) -> State { minimum_mixnode_bond: INITIAL_MIXNODE_BOND, minimum_gateway_bond: INITIAL_GATEWAY_BOND, mixnode_bond_reward_rate, - gateway_bond_reward_rate, mixnode_delegation_reward_rate, - gateway_delegation_reward_rate, mixnode_active_set_size: INITIAL_MIXNODE_ACTIVE_SET_SIZE, - gateway_active_set_size: INITIAL_GATEWAY_ACTIVE_SET_SIZE, }, mixnode_epoch_bond_reward: calculate_epoch_reward_rate( INITIAL_DEFAULT_EPOCH_LENGTH, mixnode_bond_reward_rate, ), - gateway_epoch_bond_reward: calculate_epoch_reward_rate( - INITIAL_DEFAULT_EPOCH_LENGTH, - gateway_bond_reward_rate, - ), mixnode_epoch_delegation_reward: calculate_epoch_reward_rate( INITIAL_DEFAULT_EPOCH_LENGTH, mixnode_delegation_reward_rate, ), - gateway_epoch_delegation_reward: calculate_epoch_reward_rate( - INITIAL_DEFAULT_EPOCH_LENGTH, - gateway_delegation_reward_rate, - ), } } @@ -110,21 +94,12 @@ pub fn execute( ExecuteMsg::RewardMixnode { identity, uptime } => { transactions::try_reward_mixnode(deps, env, info, identity, uptime) } - ExecuteMsg::RewardGateway { identity, uptime } => { - transactions::try_reward_gateway(deps, env, info, identity, uptime) - } ExecuteMsg::DelegateToMixnode { mix_identity } => { transactions::try_delegate_to_mixnode(deps, env, info, mix_identity) } ExecuteMsg::UndelegateFromMixnode { mix_identity } => { transactions::try_remove_delegation_from_mixnode(deps, info, mix_identity) } - ExecuteMsg::DelegateToGateway { gateway_identity } => { - transactions::try_delegate_to_gateway(deps, env, info, gateway_identity) - } - ExecuteMsg::UndelegateFromGateway { gateway_identity } => { - transactions::try_remove_delegation_from_gateway(deps, info, gateway_identity) - } } } @@ -176,37 +151,6 @@ pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> Result to_binary(&queries::query_gateway_delegations_paged( - deps, - gateway_identity, - start_after, - limit, - )?), - QueryMsg::GetAllGatewayDelegations { start_after, limit } => to_binary( - &queries::query_all_gateway_delegations_paged(deps, start_after, limit)?, - ), - QueryMsg::GetReverseGatewayDelegations { - delegation_owner, - start_after, - limit, - } => to_binary(&queries::query_reverse_gateway_delegations_paged( - deps, - delegation_owner, - start_after, - limit, - )?), - QueryMsg::GetGatewayDelegation { - gateway_identity, - address, - } => to_binary(&queries::query_gateway_delegation( - deps, - gateway_identity, - address, - )?), }; Ok(query_res?) diff --git a/contracts/mixnet/src/error.rs b/contracts/mixnet/src/error.rs index 652533d6d0..3610edee30 100644 --- a/contracts/mixnet/src/error.rs +++ b/contracts/mixnet/src/error.rs @@ -48,15 +48,9 @@ pub enum ContractError { #[error("The bond reward rate for mixnode was set to be lower than 1")] DecreasingMixnodeBondReward, - #[error("The bond reward rate for gateway was set to be lower than 1")] - DecreasingGatewayBondReward, - #[error("The delegation reward rate for mixnode was set to be lower than 1")] DecreasingMixnodeDelegationReward, - #[error("The delegation reward rate for gateway was set to be lower than 1")] - DecreasingGatewayDelegationReward, - #[error("The node had uptime larger than 100%")] UnexpectedUptime, @@ -83,10 +77,4 @@ pub enum ContractError { identity: IdentityKey, address: Addr, }, - - #[error("Could not find any delegation information associated with gateway {identity} for {address}")] - NoGatewayDelegationFound { - identity: IdentityKey, - address: Addr, - }, } diff --git a/contracts/mixnet/src/helpers.rs b/contracts/mixnet/src/helpers.rs index 0bb672dbad..de5636a0ac 100644 --- a/contracts/mixnet/src/helpers.rs +++ b/contracts/mixnet/src/helpers.rs @@ -209,10 +209,7 @@ impl<'a, T: Clone + Serialize + DeserializeOwned> Iterator for Delegations<'a, T mod tests { use super::*; use crate::queries::tests::store_n_mix_delegations; - use crate::storage::{ - all_gateway_delegations_read, all_mix_delegations_read, gateway_delegations, - mix_delegations, - }; + use crate::storage::{all_mix_delegations_read, mix_delegations}; use crate::support::tests::helpers; use cosmwasm_std::testing::mock_dependencies; use mixnet_contract::RawDelegationData; @@ -389,66 +386,4 @@ mod tests { UnpackedDelegation::new(delegation_owner2, node_identity2, raw_delegation.clone()), ); } - - #[test] - fn all_gateway_delegations() { - let mut deps = mock_dependencies(&[]); - let node_identity1: IdentityKey = "foo1".into(); - let delegation_owner1 = Addr::unchecked("bar1"); - let node_identity2: IdentityKey = "foo2".into(); - let delegation_owner2 = Addr::unchecked("bar2"); - let raw_delegation = RawDelegationData::new(1000u128.into(), 42); - let mut start_after = None; - - gateway_delegations(&mut deps.storage, &node_identity1) - .save(delegation_owner1.as_bytes(), &raw_delegation) - .unwrap(); - - let bucket = all_gateway_delegations_read::(&deps.storage); - let response = - get_all_delegations_paged::(&bucket, &start_after, 10).unwrap(); - start_after = response.start_next_after; - let delegations = response.delegations; - assert_eq!(delegations.len(), 1); - assert_eq!( - delegations[0], - UnpackedDelegation::new( - delegation_owner1.clone(), - node_identity1.clone(), - raw_delegation.clone() - ) - ); - - gateway_delegations(&mut deps.storage, &node_identity2) - .save(delegation_owner2.as_bytes(), &raw_delegation) - .unwrap(); - - let bucket = all_gateway_delegations_read::(&deps.storage); - let response = - get_all_delegations_paged::(&bucket, &start_after, 10).unwrap(); - start_after = response.start_next_after; - let delegations = response.delegations; - assert_eq!(delegations.len(), 2); - assert_eq!( - delegations[1], - UnpackedDelegation::new( - delegation_owner2.clone(), - node_identity2.clone(), - raw_delegation.clone() - ) - ); - - gateway_delegations(&mut deps.storage, &node_identity1) - .remove(delegation_owner1.as_bytes()); - - let bucket = all_gateway_delegations_read::(&deps.storage); - let response = - get_all_delegations_paged::(&bucket, &start_after, 10).unwrap(); - let delegations = response.delegations; - assert_eq!(delegations.len(), 1); - assert_eq!( - delegations[0], - UnpackedDelegation::new(delegation_owner2, node_identity2, raw_delegation.clone()), - ); - } } diff --git a/contracts/mixnet/src/queries.rs b/contracts/mixnet/src/queries.rs index 0d2c3826aa..e76d62a93c 100644 --- a/contracts/mixnet/src/queries.rs +++ b/contracts/mixnet/src/queries.rs @@ -4,19 +4,17 @@ use crate::error::ContractError; use crate::helpers::get_all_delegations_paged; use crate::storage::{ - all_gateway_delegations_read, all_mix_delegations_read, gateway_delegations_read, - gateways_owners_read, gateways_read, mix_delegations_read, mixnodes_owners_read, mixnodes_read, - read_layer_distribution, read_state_params, reverse_gateway_delegations_read, + all_mix_delegations_read, gateways_owners_read, gateways_read, mix_delegations_read, + mixnodes_owners_read, mixnodes_read, read_layer_distribution, read_state_params, reverse_mix_delegations_read, }; use config::defaults::DENOM; use cosmwasm_std::{coin, Addr, Deps, Order, StdResult}; use mixnet_contract::{ Delegation, GatewayBond, GatewayOwnershipResponse, IdentityKey, LayerDistribution, MixNodeBond, - MixOwnershipResponse, PagedAllDelegationsResponse, PagedGatewayDelegationsResponse, - PagedGatewayResponse, PagedMixDelegationsResponse, PagedMixnodeResponse, - PagedReverseGatewayDelegationsResponse, PagedReverseMixDelegationsResponse, RawDelegationData, - StateParams, + MixOwnershipResponse, PagedAllDelegationsResponse, PagedGatewayResponse, + PagedMixDelegationsResponse, PagedMixnodeResponse, PagedReverseMixDelegationsResponse, + RawDelegationData, StateParams, }; const BOND_PAGE_MAX_LIMIT: u32 = 100; @@ -211,114 +209,11 @@ pub(crate) fn query_mixnode_delegation( } } -pub(crate) fn query_gateway_delegations_paged( - deps: Deps, - gateway_identity: IdentityKey, - start_after: Option, - limit: Option, -) -> StdResult { - let limit = limit - .unwrap_or(DELEGATION_PAGE_DEFAULT_LIMIT) - .min(DELEGATION_PAGE_MAX_LIMIT) as usize; - let start = calculate_start_value(start_after); - - let delegations = gateway_delegations_read(deps.storage, &gateway_identity) - .range(start.as_deref(), None, Order::Ascending) - .take(limit) - .map(|res| { - res.map(|entry| { - Delegation::new( - Addr::unchecked(String::from_utf8(entry.0).expect( - "Non-UTF8 address used as key in bucket. The storage is corrupted!", - )), - coin(entry.1.amount.u128(), DENOM), - entry.1.block_height, - ) - }) - }) - .collect::>>()?; - - let start_next_after = delegations.last().map(|delegation| delegation.owner()); - - Ok(PagedGatewayDelegationsResponse::new( - gateway_identity, - delegations, - start_next_after, - )) -} - -pub(crate) fn query_all_gateway_delegations_paged( - deps: Deps, - start_after: Option>, - limit: Option, -) -> StdResult> { - let limit = limit - .unwrap_or(DELEGATION_PAGE_DEFAULT_LIMIT) - .min(DELEGATION_PAGE_MAX_LIMIT) as usize; - - let bucket = all_gateway_delegations_read::(deps.storage); - let start = start_after.map(|mut v| { - v.push(0); - v - }); - get_all_delegations_paged::(&bucket, &start, limit) -} - -pub(crate) fn query_reverse_gateway_delegations_paged( - deps: Deps, - delegation_owner: Addr, - start_after: Option, - limit: Option, -) -> StdResult { - let limit = limit - .unwrap_or(DELEGATION_PAGE_DEFAULT_LIMIT) - .min(DELEGATION_PAGE_MAX_LIMIT) as usize; - let start = calculate_start_value(start_after); - - let delegations = reverse_gateway_delegations_read(deps.storage, &delegation_owner) - .range(start.as_deref(), None, Order::Ascending) - .take(limit) - .map(|res| { - res.map(|entry| { - String::from_utf8(entry.0) - .expect("Non-UTF8 address used as key in bucket. The storage is corrupted!") - }) - }) - .collect::>>()?; - - let start_next_after = delegations.last().cloned(); - - Ok(PagedReverseGatewayDelegationsResponse::new( - delegation_owner, - delegations, - start_next_after, - )) -} - -// queries for delegation value of given address for particular node -pub(crate) fn query_gateway_delegation( - deps: Deps, - gateway_identity: IdentityKey, - address: Addr, -) -> Result { - match gateway_delegations_read(deps.storage, &gateway_identity).may_load(address.as_bytes())? { - Some(delegation_value) => Ok(Delegation::new( - address, - coin(delegation_value.amount.u128(), DENOM), - delegation_value.block_height, - )), - None => Err(ContractError::NoGatewayDelegationFound { - identity: gateway_identity, - address, - }), - } -} - #[cfg(test)] pub(crate) mod tests { use super::*; use crate::state::State; - use crate::storage::{config, gateway_delegations, gateways, mix_delegations, mixnodes}; + use crate::storage::{config, gateways, mix_delegations, mixnodes}; use crate::support::tests::helpers; use crate::support::tests::helpers::{ good_gateway_bond, good_mixnode_bond, raw_delegation_fixture, @@ -673,16 +568,11 @@ pub(crate) mod tests { minimum_mixnode_bond: 123u128.into(), minimum_gateway_bond: 456u128.into(), mixnode_bond_reward_rate: "1.23".parse().unwrap(), - gateway_bond_reward_rate: "4.56".parse().unwrap(), mixnode_delegation_reward_rate: "7.89".parse().unwrap(), - gateway_delegation_reward_rate: "0.12".parse().unwrap(), mixnode_active_set_size: 1000, - gateway_active_set_size: 20, }, mixnode_epoch_bond_reward: "1.23".parse().unwrap(), - gateway_epoch_bond_reward: "4.56".parse().unwrap(), mixnode_epoch_delegation_reward: "7.89".parse().unwrap(), - gateway_epoch_delegation_reward: "0.12".parse().unwrap(), }; config(deps.as_mut().storage).save(&dummy_state).unwrap(); @@ -1203,524 +1093,4 @@ pub(crate) mod tests { assert_eq!(2, page2.delegated_nodes.len()); } } - - pub fn store_n_gateway_delegations( - n: u32, - storage: &mut dyn Storage, - node_identity: &IdentityKey, - ) { - for i in 0..n { - let address = format!("address{}", i); - gateway_delegations(storage, node_identity) - .save(address.as_bytes(), &raw_delegation_fixture(42)) - .unwrap(); - } - } - - #[cfg(test)] - mod querying_for_gateway_delegations_paged { - use super::*; - use crate::storage::gateway_delegations; - - #[test] - fn retrieval_obeys_limits() { - let mut deps = helpers::init_contract(); - let limit = 2; - let node_identity: IdentityKey = "foo".into(); - store_n_gateway_delegations(100, &mut deps.storage, &node_identity); - - let page1 = query_gateway_delegations_paged( - deps.as_ref(), - node_identity, - None, - Option::from(limit), - ) - .unwrap(); - assert_eq!(limit, page1.delegations.len() as u32); - } - - #[test] - fn retrieval_has_default_limit() { - let mut deps = helpers::init_contract(); - let node_identity: IdentityKey = "foo".into(); - store_n_gateway_delegations( - DELEGATION_PAGE_DEFAULT_LIMIT * 10, - &mut deps.storage, - &node_identity, - ); - - // query without explicitly setting a limit - let page1 = - query_gateway_delegations_paged(deps.as_ref(), node_identity, None, None).unwrap(); - assert_eq!( - DELEGATION_PAGE_DEFAULT_LIMIT, - page1.delegations.len() as u32 - ); - } - - #[test] - fn retrieval_has_max_limit() { - let mut deps = helpers::init_contract(); - let node_identity: IdentityKey = "foo".into(); - store_n_gateway_delegations( - DELEGATION_PAGE_DEFAULT_LIMIT * 10, - &mut deps.storage, - &node_identity, - ); - - // query with a crazily high limit in an attempt to use too many resources - let crazy_limit = 1000 * DELEGATION_PAGE_DEFAULT_LIMIT; - let page1 = query_gateway_delegations_paged( - deps.as_ref(), - node_identity, - None, - Option::from(crazy_limit), - ) - .unwrap(); - - // we default to a decent sized upper bound instead - let expected_limit = DELEGATION_PAGE_MAX_LIMIT; - assert_eq!(expected_limit, page1.delegations.len() as u32); - } - - #[test] - fn pagination_works() { - let mut deps = helpers::init_contract(); - let node_identity: IdentityKey = "foo".into(); - - gateway_delegations(&mut deps.storage, &node_identity) - .save("1".as_bytes(), &raw_delegation_fixture(42)) - .unwrap(); - - let per_page = 2; - let page1 = query_gateway_delegations_paged( - deps.as_ref(), - node_identity.clone(), - None, - Option::from(per_page), - ) - .unwrap(); - - // page should have 1 result on it - assert_eq!(1, page1.delegations.len()); - - // save another - gateway_delegations(&mut deps.storage, &node_identity) - .save("2".as_bytes(), &raw_delegation_fixture(42)) - .unwrap(); - - // page1 should have 2 results on it - let page1 = query_gateway_delegations_paged( - deps.as_ref(), - node_identity.clone(), - None, - Option::from(per_page), - ) - .unwrap(); - assert_eq!(2, page1.delegations.len()); - - gateway_delegations(&mut deps.storage, &node_identity) - .save("3".as_bytes(), &raw_delegation_fixture(42)) - .unwrap(); - - // page1 still has 2 results - let page1 = query_gateway_delegations_paged( - deps.as_ref(), - node_identity.clone(), - None, - Option::from(per_page), - ) - .unwrap(); - assert_eq!(2, page1.delegations.len()); - - // retrieving the next page should start after the last key on this page - let start_after = Addr::unchecked("2"); - let page2 = query_gateway_delegations_paged( - deps.as_ref(), - node_identity.clone(), - Option::from(start_after), - Option::from(per_page), - ) - .unwrap(); - - assert_eq!(1, page2.delegations.len()); - - // save another one - gateway_delegations(&mut deps.storage, &node_identity) - .save("4".as_bytes(), &raw_delegation_fixture(42)) - .unwrap(); - - let start_after = Addr::unchecked("2"); - let page2 = query_gateway_delegations_paged( - deps.as_ref(), - node_identity, - Option::from(start_after), - Option::from(per_page), - ) - .unwrap(); - - // now we have 2 pages, with 2 results on the second page - assert_eq!(2, page2.delegations.len()); - } - } - - #[test] - fn gateway_deletion_query_returns_current_delegation_value() { - let mut deps = helpers::init_contract(); - let node_identity: IdentityKey = "foo".into(); - let delegation_owner = Addr::unchecked("bar"); - - gateway_delegations(&mut deps.storage, &node_identity) - .save( - delegation_owner.as_bytes(), - &&RawDelegationData::new(42u128.into(), 12_345), - ) - .unwrap(); - - assert_eq!( - Ok(Delegation::new( - delegation_owner.clone(), - coin(42, DENOM), - 12_345 - )), - query_gateway_delegation(deps.as_ref(), node_identity, delegation_owner) - ) - } - - #[test] - fn gateway_deletion_query_returns_error_if_delegation_doesnt_exist() { - let mut deps = helpers::init_contract(); - - let node_identity1: IdentityKey = "foo1".into(); - let node_identity2: IdentityKey = "foo2".into(); - let delegation_owner1 = Addr::unchecked("bar"); - let delegation_owner2 = Addr::unchecked("bar2"); - - assert_eq!( - Err(ContractError::NoGatewayDelegationFound { - identity: node_identity1.clone(), - address: delegation_owner1.clone(), - }), - query_gateway_delegation( - deps.as_ref(), - node_identity1.clone(), - delegation_owner1.clone() - ) - ); - - // add delegation from a different address - gateway_delegations(&mut deps.storage, &node_identity1) - .save(delegation_owner2.as_bytes(), &raw_delegation_fixture(42)) - .unwrap(); - - assert_eq!( - Err(ContractError::NoGatewayDelegationFound { - identity: node_identity1.clone(), - address: delegation_owner1.clone(), - }), - query_gateway_delegation( - deps.as_ref(), - node_identity1.clone(), - delegation_owner1.clone() - ) - ); - - // add delegation for a different node - gateway_delegations(&mut deps.storage, &node_identity2) - .save(delegation_owner1.as_bytes(), &raw_delegation_fixture(42)) - .unwrap(); - - assert_eq!( - Err(ContractError::NoGatewayDelegationFound { - identity: node_identity1.clone(), - address: delegation_owner1.clone() - }), - query_gateway_delegation(deps.as_ref(), node_identity1, delegation_owner1) - ) - } - - #[cfg(test)] - mod querying_for_all_gateway_delegations_paged { - use super::*; - use crate::helpers::identity_and_owner_to_bytes; - use crate::storage::gateway_delegations; - - #[test] - fn retrieval_obeys_limits() { - let mut deps = helpers::init_contract(); - let limit = 2; - let node_identity: IdentityKey = "foo".into(); - store_n_gateway_delegations(100, &mut deps.storage, &node_identity); - - let page1 = - query_all_gateway_delegations_paged(deps.as_ref(), None, Option::from(limit)) - .unwrap(); - assert_eq!(limit, page1.delegations.len() as u32); - } - - #[test] - fn retrieval_has_default_limit() { - let mut deps = helpers::init_contract(); - let node_identity: IdentityKey = "foo".into(); - store_n_gateway_delegations( - DELEGATION_PAGE_DEFAULT_LIMIT * 10, - &mut deps.storage, - &node_identity, - ); - - // query without explicitly setting a limit - let page1 = query_all_gateway_delegations_paged(deps.as_ref(), None, None).unwrap(); - assert_eq!( - DELEGATION_PAGE_DEFAULT_LIMIT, - page1.delegations.len() as u32 - ); - } - - #[test] - fn retrieval_has_max_limit() { - let mut deps = helpers::init_contract(); - let node_identity: IdentityKey = "foo".into(); - store_n_gateway_delegations( - DELEGATION_PAGE_DEFAULT_LIMIT * 10, - &mut deps.storage, - &node_identity, - ); - - // query with a crazily high limit in an attempt to use too many resources - let crazy_limit = 1000 * DELEGATION_PAGE_DEFAULT_LIMIT; - let page1 = - query_all_gateway_delegations_paged(deps.as_ref(), None, Option::from(crazy_limit)) - .unwrap(); - - // we default to a decent sized upper bound instead - let expected_limit = DELEGATION_PAGE_MAX_LIMIT; - assert_eq!(expected_limit, page1.delegations.len() as u32); - } - - #[test] - fn pagination_works() { - let mut deps = helpers::init_contract(); - let node_identity: IdentityKey = "foo".into(); - - gateway_delegations(&mut deps.storage, &node_identity) - .save("1".as_bytes(), &raw_delegation_fixture(42)) - .unwrap(); - - let per_page = 2; - let page1 = - query_all_gateway_delegations_paged(deps.as_ref(), None, Option::from(per_page)) - .unwrap(); - - // page should have 1 result on it - assert_eq!(1, page1.delegations.len()); - - // save another - gateway_delegations(&mut deps.storage, &node_identity) - .save("2".as_bytes(), &raw_delegation_fixture(42)) - .unwrap(); - - // page1 should have 2 results on it - let page1 = - query_all_gateway_delegations_paged(deps.as_ref(), None, Option::from(per_page)) - .unwrap(); - assert_eq!(2, page1.delegations.len()); - - gateway_delegations(&mut deps.storage, &node_identity) - .save("3".as_bytes(), &raw_delegation_fixture(42)) - .unwrap(); - - // page1 still has 2 results - let page1 = - query_all_gateway_delegations_paged(deps.as_ref(), None, Option::from(per_page)) - .unwrap(); - assert_eq!(2, page1.delegations.len()); - - // retrieving the next page should start after the last key on this page - let start_after = identity_and_owner_to_bytes(&node_identity, &Addr::unchecked("2")); - let page2 = query_all_gateway_delegations_paged( - deps.as_ref(), - Option::from(start_after.clone()), - Option::from(per_page), - ) - .unwrap(); - - assert_eq!(1, page2.delegations.len()); - - // save another one - gateway_delegations(&mut deps.storage, &node_identity) - .save("4".as_bytes(), &raw_delegation_fixture(42)) - .unwrap(); - - let page2 = query_all_gateway_delegations_paged( - deps.as_ref(), - Option::from(start_after), - Option::from(per_page), - ) - .unwrap(); - - // now we have 2 pages, with 2 results on the second page - assert_eq!(2, page2.delegations.len()); - } - } - - #[cfg(test)] - mod querying_for_reverse_gateway_delegations_paged { - use super::*; - use crate::storage::reverse_gateway_delegations; - - fn store_n_reverse_delegations(n: u32, storage: &mut dyn Storage, delegation_owner: &Addr) { - for i in 0..n { - let node_identity = format!("node{}", i); - reverse_gateway_delegations(storage, delegation_owner) - .save(node_identity.as_bytes(), &()) - .unwrap(); - } - } - - #[test] - fn retrieval_obeys_limits() { - let mut deps = helpers::init_contract(); - let limit = 2; - let delegation_owner = Addr::unchecked("foo"); - store_n_reverse_delegations(100, &mut deps.storage, &delegation_owner); - - let page1 = query_reverse_gateway_delegations_paged( - deps.as_ref(), - delegation_owner, - None, - Option::from(limit), - ) - .unwrap(); - assert_eq!(limit, page1.delegated_nodes.len() as u32); - } - - #[test] - fn retrieval_has_default_limit() { - let mut deps = helpers::init_contract(); - let delegation_owner = Addr::unchecked("foo"); - store_n_reverse_delegations( - DELEGATION_PAGE_DEFAULT_LIMIT * 10, - &mut deps.storage, - &delegation_owner, - ); - - // query without explicitly setting a limit - let page1 = query_reverse_gateway_delegations_paged( - deps.as_ref(), - delegation_owner, - None, - None, - ) - .unwrap(); - assert_eq!( - DELEGATION_PAGE_DEFAULT_LIMIT, - page1.delegated_nodes.len() as u32 - ); - } - - #[test] - fn retrieval_has_max_limit() { - let mut deps = helpers::init_contract(); - let delegation_owner = Addr::unchecked("foo"); - store_n_reverse_delegations( - DELEGATION_PAGE_DEFAULT_LIMIT * 10, - &mut deps.storage, - &delegation_owner, - ); - - // query with a crazy high limit in an attempt to use too many resources - let crazy_limit = 1000 * DELEGATION_PAGE_DEFAULT_LIMIT; - let page1 = query_reverse_gateway_delegations_paged( - deps.as_ref(), - delegation_owner, - None, - Option::from(crazy_limit), - ) - .unwrap(); - - // we default to a decent sized upper bound instead - let expected_limit = DELEGATION_PAGE_MAX_LIMIT; - assert_eq!(expected_limit, page1.delegated_nodes.len() as u32); - } - - #[test] - fn pagination_works() { - let mut deps = helpers::init_contract(); - let delegation_owner = Addr::unchecked("bar"); - - reverse_gateway_delegations(&mut deps.storage, &delegation_owner) - .save("1".as_bytes(), &()) - .unwrap(); - - let per_page = 2; - let page1 = query_reverse_gateway_delegations_paged( - deps.as_ref(), - delegation_owner.clone(), - None, - Option::from(per_page), - ) - .unwrap(); - - // page should have 1 result on it - assert_eq!(1, page1.delegated_nodes.len()); - - // save another - reverse_gateway_delegations(&mut deps.storage, &delegation_owner) - .save("2".as_bytes(), &()) - .unwrap(); - - // page1 should have 2 results on it - let page1 = query_reverse_gateway_delegations_paged( - deps.as_ref(), - delegation_owner.clone(), - None, - Option::from(per_page), - ) - .unwrap(); - assert_eq!(2, page1.delegated_nodes.len()); - - reverse_gateway_delegations(&mut deps.storage, &delegation_owner) - .save("3".as_bytes(), &()) - .unwrap(); - - // page1 still has 2 results - let page1 = query_reverse_gateway_delegations_paged( - deps.as_ref(), - delegation_owner.clone(), - None, - Option::from(per_page), - ) - .unwrap(); - assert_eq!(2, page1.delegated_nodes.len()); - - // retrieving the next page should start after the last key on this page - let start_after: IdentityKey = String::from("2"); - let page2 = query_reverse_gateway_delegations_paged( - deps.as_ref(), - delegation_owner.clone(), - Option::from(start_after), - Option::from(per_page), - ) - .unwrap(); - - assert_eq!(1, page2.delegated_nodes.len()); - - // save another one - reverse_gateway_delegations(&mut deps.storage, &delegation_owner) - .save("4".as_bytes(), &()) - .unwrap(); - - let start_after = String::from("2"); - let page2 = query_reverse_gateway_delegations_paged( - deps.as_ref(), - delegation_owner, - Option::from(start_after), - Option::from(per_page), - ) - .unwrap(); - - // now we have 2 pages, with 2 results on the second page - assert_eq!(2, page2.delegated_nodes.len()); - } - } } diff --git a/contracts/mixnet/src/state.rs b/contracts/mixnet/src/state.rs index c537366f07..6371e6529f 100644 --- a/contracts/mixnet/src/state.rs +++ b/contracts/mixnet/src/state.rs @@ -14,7 +14,5 @@ pub struct State { // helper values to avoid having to recalculate them on every single payment operation pub mixnode_epoch_bond_reward: Decimal, // reward per epoch expressed as a decimal like 0.05 - pub gateway_epoch_bond_reward: Decimal, // reward per epoch expressed as a decimal like 0.05 pub mixnode_epoch_delegation_reward: Decimal, // reward per epoch expressed as a decimal like 0.05 - pub gateway_epoch_delegation_reward: Decimal, // reward per epoch expressed as a decimal like 0.05 } diff --git a/contracts/mixnet/src/storage.rs b/contracts/mixnet/src/storage.rs index 21cd2c41da..80aaddecf3 100644 --- a/contracts/mixnet/src/storage.rs +++ b/contracts/mixnet/src/storage.rs @@ -32,9 +32,7 @@ const PREFIX_GATEWAYS: &[u8] = b"gt"; const PREFIX_GATEWAYS_OWNERS: &[u8] = b"go"; const PREFIX_MIX_DELEGATION: &[u8] = b"md"; -const PREFIX_GATEWAY_DELEGATION: &[u8] = b"gd"; const PREFIX_REVERSE_MIX_DELEGATION: &[u8] = b"dm"; -const PREFIX_REVERSE_GATEWAY_DELEGATION: &[u8] = b"dg"; // Contract-level stuff @@ -63,14 +61,6 @@ pub(crate) fn read_mixnode_epoch_bond_reward_rate(storage: &dyn Storage) -> Deci .mixnode_epoch_bond_reward } -pub(crate) fn read_gateway_epoch_bond_reward_rate(storage: &dyn Storage) -> Decimal { - // same justification as in `read_state_params` for the unwrap - config_read(storage) - .load() - .unwrap() - .gateway_epoch_bond_reward -} - pub(crate) fn read_mixnode_epoch_delegation_reward_rate(storage: &dyn Storage) -> Decimal { // same justification as in `read_state_params` for the unwrap config_read(storage) @@ -79,14 +69,6 @@ pub(crate) fn read_mixnode_epoch_delegation_reward_rate(storage: &dyn Storage) - .mixnode_epoch_delegation_reward } -pub(crate) fn read_gateway_epoch_delegation_reward_rate(storage: &dyn Storage) -> Decimal { - // same justification as in `read_state_params` for the unwrap - config_read(storage) - .load() - .unwrap() - .gateway_epoch_delegation_reward -} - pub fn layer_distribution(storage: &mut dyn Storage) -> Singleton { singleton(storage, LAYER_DISTRIBUTION_KEY) } @@ -214,56 +196,6 @@ pub(crate) fn increase_mix_delegated_stakes( Ok(total_rewarded) } -pub(crate) fn increase_gateway_delegated_stakes( - storage: &mut dyn Storage, - gateway_identity: IdentityKeyRef, - scaled_reward_rate: Decimal, - reward_blockstamp: u64, -) -> StdResult { - let chunk_size = queries::DELEGATION_PAGE_MAX_LIMIT as usize; - - let mut total_rewarded = Uint128::zero(); - let mut chunk_start: Option> = None; - loop { - // get `chunk_size` of delegations - let delegations_chunk = gateway_delegations_read(storage, gateway_identity) - .range(chunk_start.as_deref(), None, Order::Ascending) - .take(chunk_size) - .collect::>>()?; - - if delegations_chunk.is_empty() { - break; - } - - // append 0 byte to the last value to start with whatever is the next suceeding key - chunk_start = Some( - delegations_chunk - .last() - .unwrap() - .0 - .iter() - .cloned() - .chain(std::iter::once(0u8)) - .collect(), - ); - - // and for each of them increase the stake proportionally to the reward - // if at least `MINIMUM_BLOCK_AGE_FOR_REWARDING` blocks have been created - // since they delegated - for (delegator_address, mut delegation) in delegations_chunk.into_iter() { - if delegation.block_height + MINIMUM_BLOCK_AGE_FOR_REWARDING <= reward_blockstamp { - let reward = delegation.amount * scaled_reward_rate; - delegation.amount += reward; - total_rewarded += reward; - gateway_delegations(storage, gateway_identity) - .save(&delegator_address, &delegation)?; - } - } - } - - Ok(total_rewarded) -} - // currently not used outside tests #[cfg(test)] pub(crate) fn read_mixnode_bond( @@ -338,53 +270,6 @@ pub fn reverse_mix_delegations_read<'a>( ReadonlyBucket::multilevel(storage, &[PREFIX_REVERSE_MIX_DELEGATION, owner.as_bytes()]) } -pub fn all_gateway_delegations_read(storage: &dyn Storage) -> ReadonlyBucket -where - T: Serialize + DeserializeOwned, -{ - bucket_read(storage, PREFIX_GATEWAY_DELEGATION) -} - -pub fn gateway_delegations<'a>( - storage: &'a mut dyn Storage, - gateway_identity: IdentityKeyRef, -) -> Bucket<'a, RawDelegationData> { - Bucket::multilevel( - storage, - &[PREFIX_GATEWAY_DELEGATION, gateway_identity.as_bytes()], - ) -} - -pub fn gateway_delegations_read<'a>( - storage: &'a dyn Storage, - gateway_identity: IdentityKeyRef, -) -> ReadonlyBucket<'a, RawDelegationData> { - ReadonlyBucket::multilevel( - storage, - &[PREFIX_GATEWAY_DELEGATION, gateway_identity.as_bytes()], - ) -} - -pub fn reverse_gateway_delegations<'a>( - storage: &'a mut dyn Storage, - owner: &Addr, -) -> Bucket<'a, ()> { - Bucket::multilevel( - storage, - &[PREFIX_REVERSE_GATEWAY_DELEGATION, owner.as_bytes()], - ) -} - -pub fn reverse_gateway_delegations_read<'a>( - storage: &'a dyn Storage, - owner: &Addr, -) -> ReadonlyBucket<'a, ()> { - ReadonlyBucket::multilevel( - storage, - &[PREFIX_REVERSE_GATEWAY_DELEGATION, owner.as_bytes()], - ) -} - // currently not used outside tests #[cfg(test)] pub(crate) fn read_gateway_bond( @@ -396,17 +281,6 @@ pub(crate) fn read_gateway_bond( Ok(node.bond_amount.amount) } -// currently not used outside tests -#[cfg(test)] -pub(crate) fn read_gateway_delegation( - storage: &dyn Storage, - identity: &[u8], -) -> StdResult { - let bucket = gateways_read(storage); - let node = bucket.load(identity)?; - Ok(node.total_delegation.amount) -} - #[cfg(test)] mod tests { use super::*; @@ -499,7 +373,6 @@ mod tests { let gateway_bond = GatewayBond { bond_amount: coin(bond_value, DENOM), - total_delegation: coin(0, DENOM), owner: node_owner.clone(), block_height: 12_345, gateway: Gateway { @@ -551,39 +424,6 @@ mod tests { assert_eq!(raw_delegation2, res2); } - #[test] - fn all_gateway_delegations_read_retrieval() { - let mut deps = mock_dependencies(&[]); - let node_identity1: IdentityKey = "foo1".into(); - let delegation_owner1 = Addr::unchecked("bar1"); - let node_identity2: IdentityKey = "foo2".into(); - let delegation_owner2 = Addr::unchecked("bar2"); - let raw_delegation1 = RawDelegationData::new(1u128.into(), 1000); - let raw_delegation2 = RawDelegationData::new(2u128.into(), 2000); - - gateway_delegations(&mut deps.storage, &node_identity1) - .save(delegation_owner1.as_bytes(), &raw_delegation1) - .unwrap(); - gateway_delegations(&mut deps.storage, &node_identity2) - .save(delegation_owner2.as_bytes(), &raw_delegation2) - .unwrap(); - - let res1 = all_gateway_delegations_read::(&deps.storage) - .load(&*identity_and_owner_to_bytes( - &node_identity1, - &delegation_owner1, - )) - .unwrap(); - let res2 = all_gateway_delegations_read::(&deps.storage) - .load(&*identity_and_owner_to_bytes( - &node_identity2, - &delegation_owner2, - )) - .unwrap(); - assert_eq!(raw_delegation1, res1); - assert_eq!(raw_delegation2, res2); - } - #[cfg(test)] mod increasing_mix_delegated_stakes { use super::*; @@ -858,279 +698,4 @@ mod tests { ); } } - - #[cfg(test)] - mod increasing_gateway_delegated_stakes { - use super::*; - use crate::queries::query_gateway_delegations_paged; - use cosmwasm_std::testing::mock_dependencies; - - #[test] - fn when_there_are_no_delegations() { - let mut deps = mock_dependencies(&[]); - let node_identity: IdentityKey = "nodeidentity".into(); - - // 0.001 - let reward = Decimal::from_ratio(1u128, 1000u128); - - let total_increase = increase_gateway_delegated_stakes( - &mut deps.storage, - node_identity.as_ref(), - reward, - 42, - ) - .unwrap(); - - // there was no increase - assert!(total_increase.is_zero()); - - // there are no 'new' delegations magically added - assert!( - query_gateway_delegations_paged(deps.as_ref(), node_identity, None, None) - .unwrap() - .delegations - .is_empty() - ) - } - - #[test] - fn when_there_is_a_single_delegation() { - let mut deps = mock_dependencies(&[]); - let node_identity: IdentityKey = "nodeidentity".into(); - let delegation_blockstamp = 42; - - // 0.001 - let reward = Decimal::from_ratio(1u128, 1000u128); - - let delegator_address = Addr::unchecked("bob"); - gateway_delegations(&mut deps.storage, &node_identity) - .save( - delegator_address.as_bytes(), - &RawDelegationData::new(1000u128.into(), delegation_blockstamp), - ) - .unwrap(); - - let total_increase = increase_gateway_delegated_stakes( - &mut deps.storage, - node_identity.as_ref(), - reward, - delegation_blockstamp + 2 * MINIMUM_BLOCK_AGE_FOR_REWARDING, - ) - .unwrap(); - - assert_eq!(Uint128(1), total_increase); - - // amount is incremented, block height remains the same - assert_eq!( - RawDelegationData::new(1001u128.into(), 42), - gateway_delegations_read(&mut deps.storage, &node_identity) - .load(delegator_address.as_bytes()) - .unwrap() - ) - } - - #[test] - fn when_there_is_a_single_delegation_depending_on_blockstamp() { - let mut deps = mock_dependencies(&[]); - let node_identity: IdentityKey = "nodeidentity".into(); - let delegation_blockstamp = 42; - - // 0.001 - let reward = Decimal::from_ratio(1u128, 1000u128); - - let delegator_address = Addr::unchecked("bob"); - gateway_delegations(&mut deps.storage, &node_identity) - .save( - delegator_address.as_bytes(), - &RawDelegationData::new(1000u128.into(), delegation_blockstamp), - ) - .unwrap(); - - let total_increase = increase_gateway_delegated_stakes( - &mut deps.storage, - node_identity.as_ref(), - reward, - delegation_blockstamp + MINIMUM_BLOCK_AGE_FOR_REWARDING - 1, - ) - .unwrap(); - - // there was no increase - assert!(total_increase.is_zero()); - - // amount is not incremented - assert_eq!( - RawDelegationData::new(1000u128.into(), delegation_blockstamp), - gateway_delegations_read(&mut deps.storage, &node_identity) - .load(delegator_address.as_bytes()) - .unwrap() - ); - - let total_increase = increase_gateway_delegated_stakes( - &mut deps.storage, - node_identity.as_ref(), - reward, - delegation_blockstamp + MINIMUM_BLOCK_AGE_FOR_REWARDING, - ) - .unwrap(); - - // there is an increase now, that the lock period has passed - assert_eq!(Uint128(1), total_increase); - - // amount is incremented - assert_eq!( - RawDelegationData::new(1001u128.into(), delegation_blockstamp), - gateway_delegations_read(&mut deps.storage, &node_identity) - .load(delegator_address.as_bytes()) - .unwrap() - ) - } - - #[test] - fn when_there_are_multiple_delegations() { - let mut deps = mock_dependencies(&[]); - let node_identity: IdentityKey = "nodeidentity".into(); - let delegation_blockstamp = 42; - - // 0.001 - let reward = Decimal::from_ratio(1u128, 1000u128); - - for i in 0..100 { - let delegator_address = Addr::unchecked(format!("address{}", i)); - gateway_delegations(&mut deps.storage, &node_identity) - .save( - delegator_address.as_bytes(), - &RawDelegationData::new(1000u128.into(), delegation_blockstamp), - ) - .unwrap(); - } - - let total_increase = increase_gateway_delegated_stakes( - &mut deps.storage, - node_identity.as_ref(), - reward, - delegation_blockstamp + 2 * MINIMUM_BLOCK_AGE_FOR_REWARDING, - ) - .unwrap(); - - assert_eq!(Uint128(100), total_increase); - - for i in 0..100 { - let delegator_address = Addr::unchecked(format!("address{}", i)); - assert_eq!( - raw_delegation_fixture(1001), - gateway_delegations_read(&mut deps.storage, &node_identity) - .load(delegator_address.as_bytes()) - .unwrap() - ) - } - } - - #[test] - fn when_there_are_more_delegations_than_page_size() { - let mut deps = mock_dependencies(&[]); - let node_identity: IdentityKey = "nodeidentity".into(); - let delegation_blockstamp = 42; - - // 0.001 - let reward = Decimal::from_ratio(1u128, 1000u128); - - for i in 0..queries::DELEGATION_PAGE_MAX_LIMIT * 10 { - let delegator_address = Addr::unchecked(format!("address{}", i)); - gateway_delegations(&mut deps.storage, &node_identity) - .save( - delegator_address.as_bytes(), - &RawDelegationData::new(1000u128.into(), delegation_blockstamp), - ) - .unwrap(); - } - - let total_increase = increase_gateway_delegated_stakes( - &mut deps.storage, - node_identity.as_ref(), - reward, - delegation_blockstamp + 2 * MINIMUM_BLOCK_AGE_FOR_REWARDING, - ) - .unwrap(); - - assert_eq!( - Uint128(queries::DELEGATION_PAGE_MAX_LIMIT as u128 * 10), - total_increase - ); - - for i in 0..queries::DELEGATION_PAGE_MAX_LIMIT * 10 { - let delegator_address = Addr::unchecked(format!("address{}", i)); - assert_eq!( - raw_delegation_fixture(1001), - gateway_delegations_read(&mut deps.storage, &node_identity) - .load(delegator_address.as_bytes()) - .unwrap() - ) - } - } - } - - #[cfg(test)] - mod reverse_gateway_delegations { - use super::*; - use crate::support::tests::helpers; - - #[test] - fn reverse_gateway_delegation_exists() { - let mut deps = helpers::init_contract(); - let node_identity: IdentityKey = "foo".into(); - let delegation_owner = Addr::unchecked("bar"); - - reverse_gateway_delegations(&mut deps.storage, &delegation_owner) - .save(node_identity.as_bytes(), &()) - .unwrap(); - - assert!( - reverse_gateway_delegations_read(deps.as_ref().storage, &delegation_owner) - .may_load(node_identity.as_bytes()) - .unwrap() - .is_some(), - ); - } - - #[test] - fn reverse_gateway_delegation_returns_none_if_delegation_doesnt_exist() { - let mut deps = helpers::init_contract(); - - let node_identity1: IdentityKey = "foo1".into(); - let node_identity2: IdentityKey = "foo2".into(); - let delegation_owner1 = Addr::unchecked("bar"); - let delegation_owner2 = Addr::unchecked("bar2"); - - assert!( - reverse_gateway_delegations_read(deps.as_ref().storage, &delegation_owner1) - .may_load(node_identity1.as_bytes()) - .unwrap() - .is_none() - ); - - // add delegation for a different node - reverse_gateway_delegations(&mut deps.storage, &delegation_owner1) - .save(node_identity2.as_bytes(), &()) - .unwrap(); - - assert!( - reverse_gateway_delegations_read(deps.as_ref().storage, &delegation_owner1) - .may_load(node_identity1.as_bytes()) - .unwrap() - .is_none() - ); - - // add delegation from a different owner - reverse_gateway_delegations(&mut deps.storage, &delegation_owner2) - .save(node_identity1.as_bytes(), &()) - .unwrap(); - - assert!( - reverse_gateway_delegations_read(deps.as_ref().storage, &delegation_owner1) - .may_load(node_identity1.as_bytes()) - .unwrap() - .is_none() - ); - } - } } diff --git a/contracts/mixnet/src/transactions.rs b/contracts/mixnet/src/transactions.rs index 7b2ec5c14c..8173243bbc 100644 --- a/contracts/mixnet/src/transactions.rs +++ b/contracts/mixnet/src/transactions.rs @@ -226,18 +226,13 @@ pub(crate) fn try_add_gateway( let minimum_bond = read_state_params(deps.storage).minimum_gateway_bond; validate_gateway_bond(&info.funds, minimum_bond)?; - let mut bond = GatewayBond::new( + let bond = GatewayBond::new( info.funds[0].clone(), info.sender.clone(), env.block.height, gateway, ); - // this might potentially require more gas if a significant number of delegations was there - let delegations_bucket = gateway_delegations_read(deps.storage, &bond.gateway.identity_key); - let existing_delegation = total_delegations(delegations_bucket)?; - bond.total_delegation = existing_delegation; - let identity = bond.identity(); gateways(deps.storage).save(identity.as_bytes(), &bond)?; gateways_owners(deps.storage).save(sender_bytes, identity)?; @@ -315,50 +310,28 @@ pub(crate) fn try_update_state_params( return Err(ContractError::DecreasingMixnodeBondReward); } - if params.gateway_bond_reward_rate < Decimal::one() { - return Err(ContractError::DecreasingGatewayBondReward); - } - if params.mixnode_delegation_reward_rate < Decimal::one() { return Err(ContractError::DecreasingMixnodeDelegationReward); } - if params.gateway_delegation_reward_rate < Decimal::one() { - return Err(ContractError::DecreasingGatewayDelegationReward); - } - - // if we're updating epoch length, recalculate rewards for both mixnodes and gateways + // if we're updating epoch length, recalculate rewards for mixnodes if state.params.epoch_length != params.epoch_length { state.mixnode_epoch_bond_reward = calculate_epoch_reward_rate(params.epoch_length, params.mixnode_bond_reward_rate); - state.gateway_epoch_bond_reward = - calculate_epoch_reward_rate(params.epoch_length, params.gateway_bond_reward_rate); state.mixnode_epoch_delegation_reward = calculate_epoch_reward_rate(params.epoch_length, params.mixnode_delegation_reward_rate); - state.gateway_epoch_delegation_reward = - calculate_epoch_reward_rate(params.epoch_length, params.gateway_delegation_reward_rate); } else { - // if mixnode or gateway rewards changed, recalculate respective values + // if mixnode rewards changed, recalculate respective values if state.params.mixnode_bond_reward_rate != params.mixnode_bond_reward_rate { state.mixnode_epoch_bond_reward = calculate_epoch_reward_rate(params.epoch_length, params.mixnode_bond_reward_rate); } - if state.params.gateway_bond_reward_rate != params.gateway_bond_reward_rate { - state.gateway_epoch_bond_reward = - calculate_epoch_reward_rate(params.epoch_length, params.gateway_bond_reward_rate); - } if state.params.mixnode_delegation_reward_rate != params.mixnode_delegation_reward_rate { state.mixnode_epoch_delegation_reward = calculate_epoch_reward_rate( params.epoch_length, params.mixnode_delegation_reward_rate, ); } - if state.params.gateway_delegation_reward_rate != params.gateway_delegation_reward_rate { - state.gateway_epoch_delegation_reward = calculate_epoch_reward_rate( - params.epoch_length, - params.gateway_delegation_reward_rate, - ); - } } state.params = params; @@ -443,81 +416,6 @@ pub(crate) fn try_reward_mixnode( }) } -// Note: if any changes are made to this function or anything it is calling down the stack, -// for example delegation reward distribution, the gas limits must be retested and both -// validator-api/src/rewarding/mod.rs::{GATEWAY_REWARD_OP_BASE_GAS_LIMIT, PER_GATEWAY_DELEGATION_GAS_INCREASE} -// must be updated appropriately. -pub(crate) fn try_reward_gateway( - deps: DepsMut, - env: Env, - info: MessageInfo, - gateway_identity: IdentityKey, - uptime: u32, -) -> Result { - let state = config_read(deps.storage).load().unwrap(); - - // check if this is executed by the owner, if not reject the transaction - if info.sender != state.network_monitor_address { - return Err(ContractError::Unauthorized); - } - - // optimisation for uptime being 0. No rewards will be given so just terminate here - if uptime == 0 { - return Ok(Response { - submessages: vec![], - messages: vec![], - attributes: vec![ - attr("bond increase", Uint128(0)), - attr("total delegation increase", Uint128(0)), - ], - data: None, - }); - } - - // check if the bond even exists - let mut current_bond = match gateways_read(deps.storage).load(gateway_identity.as_bytes()) { - Ok(bond) => bond, - Err(_) => { - return Ok(Response { - attributes: vec![attr("result", "bond not found")], - ..Default::default() - }); - } - }; - - let bond_reward_rate = read_gateway_epoch_bond_reward_rate(deps.storage); - let delegation_reward_rate = read_gateway_epoch_delegation_reward_rate(deps.storage); - let scaled_bond_reward_rate = scale_reward_by_uptime(bond_reward_rate, uptime)?; - let scaled_delegation_reward_rate = scale_reward_by_uptime(delegation_reward_rate, uptime)?; - - let mut node_reward = Uint128(0); - let total_delegation_reward = increase_gateway_delegated_stakes( - deps.storage, - &gateway_identity, - scaled_delegation_reward_rate, - env.block.height, - )?; - - // update current bond with the reward given to the node and the delegators - // if it has been bonded for long enough - if current_bond.block_height + MINIMUM_BLOCK_AGE_FOR_REWARDING <= env.block.height { - node_reward = current_bond.bond_amount.amount * scaled_bond_reward_rate; - current_bond.bond_amount.amount += node_reward; - current_bond.total_delegation.amount += total_delegation_reward; - gateways(deps.storage).save(gateway_identity.as_bytes(), ¤t_bond)?; - } - - Ok(Response { - submessages: vec![], - messages: vec![], - attributes: vec![ - attr("bond increase", node_reward), - attr("total delegation increase", total_delegation_reward), - ], - data: None, - }) -} - fn validate_delegation_stake(delegation: &[Coin]) -> Result<(), ContractError> { // check if anything was put as delegation if delegation.is_empty() { @@ -630,119 +528,19 @@ pub(crate) fn try_remove_delegation_from_mixnode( } } -pub(crate) fn try_delegate_to_gateway( - deps: DepsMut, - env: Env, - info: MessageInfo, - gateway_identity: IdentityKey, -) -> Result { - // check if the delegation contains any funds of the appropriate denomination - validate_delegation_stake(&info.funds)?; - - // check if the target node actually exists - let mut gateways_bucket = gateways(deps.storage); - let mut current_bond = match gateways_bucket.load(gateway_identity.as_bytes()) { - Ok(bond) => bond, - Err(_) => { - return Err(ContractError::GatewayBondNotFound { - identity: gateway_identity, - }); - } - }; - - // update total_delegation of this node - current_bond.total_delegation.amount += info.funds[0].amount; - gateways_bucket.save(gateway_identity.as_bytes(), ¤t_bond)?; - - let mut delegation_bucket = gateway_delegations(deps.storage, &gateway_identity); - let sender_bytes = info.sender.as_bytes(); - - // write the delegation - let new_amount = match delegation_bucket.may_load(sender_bytes)? { - Some(existing_delegation) => existing_delegation.amount + info.funds[0].amount, - None => info.funds[0].amount, - }; - // the block height is reset, if it existed - let new_delegation = RawDelegationData::new(new_amount, env.block.height); - delegation_bucket.save(sender_bytes, &new_delegation)?; - - reverse_gateway_delegations(deps.storage, &info.sender) - .save(gateway_identity.as_bytes(), &())?; - - Ok(Response::default()) -} - -pub(crate) fn try_remove_delegation_from_gateway( - deps: DepsMut, - info: MessageInfo, - gateway_identity: IdentityKey, -) -> Result { - let mut delegation_bucket = gateway_delegations(deps.storage, &gateway_identity); - let sender_bytes = info.sender.as_bytes(); - match delegation_bucket.may_load(sender_bytes)? { - Some(delegation) => { - // remove delegation from the buckets - delegation_bucket.remove(sender_bytes); - reverse_gateway_delegations(deps.storage, &info.sender) - .remove(gateway_identity.as_bytes()); - - // send delegated funds back to the delegation owner - let messages = vec![BankMsg::Send { - to_address: info.sender.to_string(), - amount: coins(delegation.amount.u128(), DENOM), - } - .into()]; - - // update total_delegation of this node - let mut gateways_bucket = gateways(deps.storage); - // in some rare cases the gateway bond might no longer exist as the node unbonded - // before delegation was removed. that is fine - if let Some(mut existing_bond) = - gateways_bucket.may_load(gateway_identity.as_bytes())? - { - // we should NEVER underflow here, if we do, it means we have some serious error in our logic - existing_bond.total_delegation.amount = existing_bond - .total_delegation - .amount - .checked_sub(delegation.amount) - .unwrap(); - gateways_bucket.save(gateway_identity.as_bytes(), &existing_bond)?; - } - - Ok(Response { - submessages: Vec::new(), - messages, - attributes: Vec::new(), - data: None, - }) - } - None => Err(ContractError::NoGatewayDelegationFound { - identity: gateway_identity, - address: info.sender, - }), - } -} - #[cfg(test)] pub mod tests { use super::*; use crate::contract::{ - execute, query, INITIAL_DEFAULT_EPOCH_LENGTH, INITIAL_GATEWAY_BOND, - INITIAL_GATEWAY_BOND_REWARD_RATE, INITIAL_GATEWAY_DELEGATION_REWARD_RATE, - INITIAL_MIXNODE_BOND, INITIAL_MIXNODE_BOND_REWARD_RATE, - INITIAL_MIXNODE_DELEGATION_REWARD_RATE, + execute, query, INITIAL_DEFAULT_EPOCH_LENGTH, INITIAL_GATEWAY_BOND, INITIAL_MIXNODE_BOND, + INITIAL_MIXNODE_BOND_REWARD_RATE, INITIAL_MIXNODE_DELEGATION_REWARD_RATE, }; use crate::helpers::calculate_epoch_reward_rate; use crate::queries::DELEGATION_PAGE_DEFAULT_LIMIT; - use crate::storage::{ - gateway_delegations, gateway_delegations_read, layer_distribution_read, - mix_delegations_read, read_gateway_bond, read_gateway_epoch_bond_reward_rate, - read_mixnode_bond, - }; + use crate::storage::{layer_distribution_read, mix_delegations_read, read_mixnode_bond}; use crate::support::tests::helpers; use crate::support::tests::helpers::{ - add_gateway, add_mixnode, gateway_fixture, good_gateway_bond, good_mixnode_bond, - mix_node_fixture, raw_delegation_fixture, + add_mixnode, good_gateway_bond, good_mixnode_bond, mix_node_fixture, raw_delegation_fixture, }; use cosmwasm_std::testing::{mock_env, mock_info}; use cosmwasm_std::{coin, coins, from_binary, Addr, Uint128}; @@ -750,7 +548,7 @@ pub mod tests { ExecuteMsg, LayerDistribution, PagedGatewayResponse, PagedMixnodeResponse, QueryMsg, UnpackedDelegation, }; - use queries::tests::{store_n_gateway_delegations, store_n_mix_delegations}; + use queries::tests::store_n_mix_delegations; #[test] fn validating_mixnode_bond() { @@ -1596,15 +1394,10 @@ pub mod tests { minimum_mixnode_bond: INITIAL_MIXNODE_BOND, minimum_gateway_bond: INITIAL_GATEWAY_BOND, mixnode_bond_reward_rate: Decimal::percent(INITIAL_MIXNODE_BOND_REWARD_RATE), - gateway_bond_reward_rate: Decimal::percent(INITIAL_GATEWAY_BOND_REWARD_RATE), mixnode_delegation_reward_rate: Decimal::percent( INITIAL_MIXNODE_DELEGATION_REWARD_RATE, ), - gateway_delegation_reward_rate: Decimal::percent( - INITIAL_GATEWAY_DELEGATION_REWARD_RATE, - ), mixnode_active_set_size: 42, // change something - gateway_active_set_size: 5, }; // cannot be updated from non-owner account @@ -1656,93 +1449,7 @@ pub mod tests { new_state.mixnode_epoch_delegation_reward ); - // gateway_epoch_rewards are recalculated if annual reward rate is changed - let current_gateway_bond_reward_rate = - read_gateway_epoch_bond_reward_rate(deps.as_ref().storage); - let current_gateway_delegation_reward_rate = - read_gateway_epoch_delegation_reward_rate(deps.as_ref().storage); - let new_gateway_bond_reward_rate = Decimal::percent(120); - let new_gateway_delegation_reward_rate = Decimal::percent(120); - - // sanity check to make sure we are actually updating the values (in case we changed defaults at some point) - assert_ne!( - new_gateway_bond_reward_rate, - current_gateway_bond_reward_rate - ); - assert_ne!( - new_gateway_delegation_reward_rate, - current_gateway_delegation_reward_rate - ); - - let mut new_params = current_state.params.clone(); - new_params.gateway_bond_reward_rate = new_gateway_bond_reward_rate; - new_params.gateway_delegation_reward_rate = new_gateway_delegation_reward_rate; - - let info = mock_info("creator", &[]); - try_update_state_params(deps.as_mut(), info, new_params.clone()).unwrap(); - - let new_state = config_read(deps.as_ref().storage).load().unwrap(); - let expected_bond = - calculate_epoch_reward_rate(new_params.epoch_length, new_gateway_bond_reward_rate); - let expected_delegation = calculate_epoch_reward_rate( - new_params.epoch_length, - new_gateway_delegation_reward_rate, - ); - assert_eq!(expected_bond, new_state.gateway_epoch_bond_reward); - assert_eq!( - expected_delegation, - new_state.gateway_epoch_delegation_reward - ); - - // if annual reward rate is changed for both mixnodes and gateways in a single update operation, - // both mixnode_epoch_rewards and gateway_epoch_rewards are recalculated - let current_state = config_read(deps.as_ref().storage).load().unwrap(); - let new_mixnode_bond_reward_rate = Decimal::percent(130); - let new_gateway_bond_reward_rate = Decimal::percent(130); - assert_ne!( - new_mixnode_bond_reward_rate, - current_state.params.mixnode_bond_reward_rate - ); - assert_ne!( - new_gateway_bond_reward_rate, - current_state.params.gateway_bond_reward_rate - ); - - let mut new_params = current_state.params.clone(); - new_params.mixnode_bond_reward_rate = new_mixnode_bond_reward_rate; - new_params.mixnode_delegation_reward_rate = new_mixnode_delegation_reward_rate; - new_params.gateway_bond_reward_rate = new_gateway_bond_reward_rate; - new_params.gateway_delegation_reward_rate = new_gateway_delegation_reward_rate; - - let info = mock_info("creator", &[]); - try_update_state_params(deps.as_mut(), info, new_params.clone()).unwrap(); - - let new_state = config_read(deps.as_ref().storage).load().unwrap(); - let expected_mixnode_bond = - calculate_epoch_reward_rate(new_params.epoch_length, new_mixnode_bond_reward_rate); - let expected_mixnode_delegation = calculate_epoch_reward_rate( - new_params.epoch_length, - new_mixnode_delegation_reward_rate, - ); - assert_eq!(expected_mixnode_bond, new_state.mixnode_epoch_bond_reward); - assert_eq!( - expected_mixnode_delegation, - new_state.mixnode_epoch_delegation_reward - ); - - let expected_gateway_bond = - calculate_epoch_reward_rate(new_params.epoch_length, new_gateway_bond_reward_rate); - let expected_gateway_delegation = calculate_epoch_reward_rate( - new_params.epoch_length, - new_gateway_delegation_reward_rate, - ); - assert_eq!(expected_gateway_bond, new_state.gateway_epoch_bond_reward); - assert_eq!( - expected_gateway_delegation, - new_state.gateway_epoch_delegation_reward - ); - - // both mixnode_epoch_rewards and gateway_epoch_rewards are updated on epoch length change + // mixnode_epoch_rewards is updated on epoch length change let new_epoch_length = 42; // sanity check to make sure we are actually updating the value (in case we changed defaults at some point) assert_ne!(new_epoch_length, current_state.params.epoch_length); @@ -1764,18 +1471,6 @@ pub mod tests { expected_mixnode_delegation, new_state.mixnode_epoch_delegation_reward ); - - let expected_gateway_bond = - calculate_epoch_reward_rate(new_epoch_length, new_params.gateway_bond_reward_rate); - let expected_gateway_delegation = calculate_epoch_reward_rate( - new_epoch_length, - new_params.gateway_delegation_reward_rate, - ); - assert_eq!(expected_gateway_bond, new_state.gateway_epoch_bond_reward); - assert_eq!( - expected_gateway_delegation, - new_state.gateway_epoch_delegation_reward - ); } #[test] @@ -2016,241 +1711,6 @@ pub mod tests { ); } - #[test] - fn rewarding_gateway() { - let mut deps = helpers::init_contract(); - let mut env = mock_env(); - let current_state = config(deps.as_mut().storage).load().unwrap(); - let network_monitor_address = current_state.network_monitor_address; - - let node_owner: Addr = Addr::unchecked("node-owner"); - let node_identity: IdentityKey = "nodeidentity".into(); - - // errors out if executed by somebody else than network monitor - let info = mock_info("not-the-monitor", &[]); - let res = try_reward_gateway(deps.as_mut(), env.clone(), info, node_identity.clone(), 100); - assert_eq!(res, Err(ContractError::Unauthorized)); - - // returns bond not found attribute if the target owner hasn't bonded any gateways - let info = mock_info(network_monitor_address.as_ref(), &[]); - let res = try_reward_gateway(deps.as_mut(), env.clone(), info, node_identity.clone(), 100) - .unwrap(); - assert_eq!(vec![attr("result", "bond not found")], res.attributes); - - let initial_bond = 100_000000; - let initial_delegation = 200_000000; - let gateway_bond = GatewayBond { - bond_amount: coin(initial_bond, DENOM), - total_delegation: coin(initial_delegation, DENOM), - owner: node_owner.clone(), - block_height: env.block.height, - gateway: Gateway { - identity_key: node_identity.clone(), - ..gateway_fixture() - }, - }; - - gateways(deps.as_mut().storage) - .save(node_identity.as_bytes(), &gateway_bond) - .unwrap(); - - gateway_delegations(&mut deps.storage, &node_identity) - .save(b"delegator", &raw_delegation_fixture(initial_delegation)) - .unwrap(); - - env.block.height += 2 * MINIMUM_BLOCK_AGE_FOR_REWARDING; - - let bond_reward_rate = read_gateway_epoch_bond_reward_rate(deps.as_ref().storage); - let delegation_reward_rate = - read_gateway_epoch_delegation_reward_rate(deps.as_ref().storage); - let expected_bond_reward = Uint128(initial_bond) * bond_reward_rate; - let expected_delegation_reward = Uint128(initial_delegation) * delegation_reward_rate; - - // the node's bond and delegations are correctly increased and scaled by uptime - // if node was 100% up, it will get full epoch reward - let expected_bond = expected_bond_reward + Uint128(initial_bond); - let expected_delegation = expected_delegation_reward + Uint128(initial_delegation); - - let info = mock_info(network_monitor_address.as_ref(), &[]); - let res = try_reward_gateway(deps.as_mut(), env.clone(), info, node_identity.clone(), 100) - .unwrap(); - - assert_eq!( - expected_bond, - read_gateway_bond(deps.as_ref().storage, node_identity.as_bytes()).unwrap() - ); - - assert_eq!( - expected_delegation, - read_gateway_delegation(deps.as_ref().storage, node_identity.as_bytes()).unwrap() - ); - - assert_eq!( - vec![ - attr("bond increase", expected_bond_reward), - attr("total delegation increase", expected_delegation_reward), - ], - res.attributes - ); - - // if node was 20% up, it will get 1/5th of epoch reward - let scaled_bond_reward = scale_reward_by_uptime(bond_reward_rate, 20).unwrap(); - let scaled_delegation_reward = scale_reward_by_uptime(delegation_reward_rate, 20).unwrap(); - let expected_bond_reward = expected_bond * scaled_bond_reward; - let expected_delegation_reward = expected_delegation * scaled_delegation_reward; - let expected_bond = expected_bond_reward + expected_bond; - let expected_delegation = expected_delegation_reward + expected_delegation; - - let info = mock_info(network_monitor_address.as_ref(), &[]); - let res = try_reward_gateway(deps.as_mut(), env.clone(), info, node_identity.clone(), 20) - .unwrap(); - - assert_eq!( - expected_bond, - read_gateway_bond(deps.as_ref().storage, node_identity.as_bytes()).unwrap() - ); - - assert_eq!( - expected_delegation, - read_gateway_delegation(deps.as_ref().storage, node_identity.as_bytes()).unwrap() - ); - - assert_eq!( - vec![ - attr("bond increase", expected_bond_reward), - attr("total delegation increase", expected_delegation_reward), - ], - res.attributes - ); - } - - #[test] - fn rewarding_gateway_blockstamp_based() { - let mut deps = helpers::init_contract(); - let mut env = mock_env(); - let current_state = config(deps.as_mut().storage).load().unwrap(); - let network_monitor_address = current_state.network_monitor_address; - - let node_owner: Addr = Addr::unchecked("node-owner"); - let node_identity: IdentityKey = "nodeidentity".into(); - - let initial_bond = 100_000000; - let initial_delegation = 200_000000; - let gateway_bond = GatewayBond { - bond_amount: coin(initial_bond, DENOM), - total_delegation: coin(initial_delegation, DENOM), - owner: node_owner.clone(), - block_height: env.block.height, - gateway: Gateway { - identity_key: node_identity.clone(), - ..gateway_fixture() - }, - }; - - gateways(deps.as_mut().storage) - .save(node_identity.as_bytes(), &gateway_bond) - .unwrap(); - - // delegation happens later, but not later enough - env.block.height += MINIMUM_BLOCK_AGE_FOR_REWARDING - 1; - - gateway_delegations(&mut deps.storage, &node_identity) - .save( - b"delegator", - &RawDelegationData::new(initial_delegation.into(), env.block.height), - ) - .unwrap(); - - let bond_reward_rate = read_gateway_epoch_bond_reward_rate(deps.as_ref().storage); - let delegation_reward_rate = - read_gateway_epoch_delegation_reward_rate(deps.as_ref().storage); - let scaled_bond_reward = scale_reward_by_uptime(bond_reward_rate, 100).unwrap(); - let scaled_delegation_reward = scale_reward_by_uptime(delegation_reward_rate, 100).unwrap(); - - // no reward is due - let expected_bond_reward = Uint128(0); - let expected_delegation_reward = Uint128(0); - let expected_bond = expected_bond_reward + Uint128(initial_bond); - let expected_delegation = expected_delegation_reward + Uint128(initial_delegation); - - let info = mock_info(network_monitor_address.as_ref(), &[]); - let res = try_reward_gateway(deps.as_mut(), env.clone(), info, node_identity.clone(), 100) - .unwrap(); - - assert_eq!( - expected_bond, - read_gateway_bond(deps.as_ref().storage, node_identity.as_bytes()).unwrap() - ); - assert_eq!( - expected_delegation, - read_gateway_delegation(deps.as_ref().storage, node_identity.as_bytes()).unwrap() - ); - - assert_eq!( - vec![ - attr("bond increase", expected_bond_reward), - attr("total delegation increase", expected_delegation_reward), - ], - res.attributes - ); - - // reward can happen now, but only for bonded node - env.block.height += 1; - let expected_bond_reward = expected_bond * scaled_bond_reward; - let expected_delegation_reward = Uint128(0); - let expected_bond = expected_bond_reward + expected_bond; - let expected_delegation = expected_delegation_reward + expected_delegation; - - let info = mock_info(network_monitor_address.as_ref(), &[]); - let res = try_reward_gateway(deps.as_mut(), env.clone(), info, node_identity.clone(), 100) - .unwrap(); - - assert_eq!( - expected_bond, - read_gateway_bond(deps.as_ref().storage, node_identity.as_bytes()).unwrap() - ); - assert_eq!( - expected_delegation, - read_gateway_delegation(deps.as_ref().storage, node_identity.as_bytes()).unwrap() - ); - - assert_eq!( - vec![ - attr("bond increase", expected_bond_reward), - attr("total delegation increase", expected_delegation_reward), - ], - res.attributes - ); - - // reward happens now, both for node owner and delegators - env.block.height += MINIMUM_BLOCK_AGE_FOR_REWARDING - 1; - let expected_bond_reward = expected_bond * scaled_bond_reward; - let expected_delegation_reward = expected_delegation * scaled_delegation_reward; - let expected_bond = expected_bond_reward + expected_bond; - let expected_delegation = expected_delegation_reward + expected_delegation; - - let info = mock_info(network_monitor_address.as_ref(), &[]); - let res = try_reward_gateway(deps.as_mut(), env.clone(), info, node_identity.clone(), 100) - .unwrap(); - - assert_eq!( - expected_bond, - read_gateway_bond(deps.as_ref().storage, node_identity.as_bytes()).unwrap() - ); - assert_eq!( - expected_delegation, - read_gateway_delegation(deps.as_ref().storage, node_identity.as_bytes()).unwrap() - ); - - assert_eq!( - vec![ - attr("bond increase", expected_bond_reward), - attr("total delegation increase", expected_delegation_reward), - ], - res.attributes - ); - } - #[cfg(test)] mod delegation_stake_validation { use super::*; @@ -3100,800 +2560,6 @@ pub mod tests { ); } - #[cfg(test)] - mod gateway_stake_delegation { - use super::*; - use crate::storage::gateway_delegations_read; - use crate::support::tests::helpers::add_gateway; - - #[test] - fn fails_if_node_doesnt_exist() { - let mut deps = helpers::init_contract(); - assert_eq!( - Err(ContractError::GatewayBondNotFound { - identity: "non-existent-gateway-identity".into() - }), - try_delegate_to_gateway( - deps.as_mut(), - mock_env(), - mock_info("sender", &coins(123, DENOM)), - "non-existent-gateway-identity".into() - ) - ); - } - - #[test] - fn succeeds_for_existing_node() { - let mut deps = helpers::init_contract(); - let gateway_owner = "bob"; - let identity = add_gateway(gateway_owner, good_gateway_bond(), &mut deps); - let delegation_owner = Addr::unchecked("sender"); - - let delegation = coin(123, DENOM); - assert!(try_delegate_to_gateway( - deps.as_mut(), - mock_env(), - mock_info(delegation_owner.as_str(), &vec![delegation.clone()]), - identity.clone() - ) - .is_ok()); - - assert_eq!( - RawDelegationData::new(delegation.amount, mock_env().block.height), - gateway_delegations_read(&deps.storage, &identity) - .load(delegation_owner.as_bytes()) - .unwrap() - ); - assert!( - reverse_gateway_delegations_read(&deps.storage, &delegation_owner) - .load(identity.as_bytes()) - .is_ok() - ); - - // node's "total_delegation" is increased - assert_eq!( - delegation, - gateways_read(&deps.storage) - .load(identity.as_bytes()) - .unwrap() - .total_delegation - ) - } - - #[test] - fn fails_if_node_unbonded() { - let mut deps = helpers::init_contract(); - - let gateway_owner = "bob"; - let identity = add_gateway(gateway_owner, good_gateway_bond(), &mut deps); - let delegation_owner = Addr::unchecked("sender"); - - try_remove_gateway(deps.as_mut(), mock_info(gateway_owner, &[])).unwrap(); - - assert_eq!( - Err(ContractError::GatewayBondNotFound { - identity: identity.clone() - }), - try_delegate_to_gateway( - deps.as_mut(), - mock_env(), - mock_info(delegation_owner.as_str(), &coins(123, DENOM)), - identity - ) - ); - } - - #[test] - fn succeeds_if_node_rebonded() { - let mut deps = helpers::init_contract(); - - let gateway_owner = "bob"; - add_gateway(gateway_owner, good_gateway_bond(), &mut deps); - try_remove_gateway(deps.as_mut(), mock_info(gateway_owner, &[])).unwrap(); - let identity = add_gateway(gateway_owner, good_gateway_bond(), &mut deps); - let delegation = coin(123, DENOM); - let delegation_owner = Addr::unchecked("sender"); - - assert!(try_delegate_to_gateway( - deps.as_mut(), - mock_env(), - mock_info(delegation_owner.as_str(), &vec![delegation.clone()]), - identity.clone() - ) - .is_ok()); - - assert_eq!( - RawDelegationData::new(delegation.amount, mock_env().block.height), - gateway_delegations_read(&deps.storage, &identity) - .load(delegation_owner.as_bytes()) - .unwrap() - ); - assert!( - reverse_gateway_delegations_read(&deps.storage, &delegation_owner) - .load(identity.as_bytes()) - .is_ok() - ); - - // node's "total_delegation" is increased - assert_eq!( - delegation, - gateways_read(&deps.storage) - .load(identity.as_bytes()) - .unwrap() - .total_delegation - ) - } - - #[test] - fn is_possible_for_an_already_delegated_node() { - let mut deps = helpers::init_contract(); - let gateway_owner = "bob"; - let identity = add_gateway(gateway_owner, good_gateway_bond(), &mut deps); - let delegation_owner = Addr::unchecked("sender"); - - let delegation1 = coin(100, DENOM); - let delegation2 = coin(50, DENOM); - - try_delegate_to_gateway( - deps.as_mut(), - mock_env(), - mock_info(delegation_owner.as_str(), &vec![delegation1.clone()]), - identity.clone(), - ) - .unwrap(); - - try_delegate_to_gateway( - deps.as_mut(), - mock_env(), - mock_info(delegation_owner.as_str(), &vec![delegation2.clone()]), - identity.clone(), - ) - .unwrap(); - - assert_eq!( - RawDelegationData::new( - delegation1.amount + delegation2.amount, - mock_env().block.height - ), - gateway_delegations_read(&deps.storage, &identity) - .load(delegation_owner.as_bytes()) - .unwrap() - ); - assert!( - reverse_gateway_delegations_read(&deps.storage, &delegation_owner) - .load(identity.as_bytes()) - .is_ok() - ); - - // node's "total_delegation" is sum of both - assert_eq!( - delegation1.amount + delegation2.amount, - gateways_read(&deps.storage) - .load(identity.as_bytes()) - .unwrap() - .total_delegation - .amount - ) - } - - #[test] - fn block_height_is_updated_on_new_delegation() { - let mut deps = helpers::init_contract(); - let gateway_owner = "bob"; - let identity = add_gateway(gateway_owner, good_gateway_bond(), &mut deps); - let delegation_owner = Addr::unchecked("sender"); - let delegation = coin(100, DENOM); - - let env1 = mock_env(); - let mut env2 = mock_env(); - let initial_height = env1.block.height; - let updated_height = initial_height + 42; - // second env has grown in block height - env2.block.height = updated_height; - - try_delegate_to_gateway( - deps.as_mut(), - env1, - mock_info(delegation_owner.as_str(), &vec![delegation.clone()]), - identity.clone(), - ) - .unwrap(); - - assert_eq!( - RawDelegationData::new(delegation.amount, initial_height), - gateway_delegations_read(&deps.storage, &identity) - .load(delegation_owner.as_bytes()) - .unwrap() - ); - - try_delegate_to_gateway( - deps.as_mut(), - env2, - mock_info(delegation_owner.as_str(), &vec![delegation.clone()]), - identity.clone(), - ) - .unwrap(); - - assert_eq!( - RawDelegationData::new(delegation.amount + delegation.amount, updated_height), - gateway_delegations_read(&deps.storage, &identity) - .load(delegation_owner.as_bytes()) - .unwrap() - ); - } - - #[test] - fn block_height_is_not_updated_on_different_delegator() { - let mut deps = helpers::init_contract(); - let gateway_owner = "bob"; - let identity = add_gateway(gateway_owner, good_gateway_bond(), &mut deps); - let delegation_owner1 = Addr::unchecked("sender1"); - let delegation_owner2 = Addr::unchecked("sender2"); - let delegation1 = coin(100, DENOM); - let delegation2 = coin(120, DENOM); - - let env1 = mock_env(); - let mut env2 = mock_env(); - let initial_height = env1.block.height; - let second_height = initial_height + 42; - // second env has grown in block height - env2.block.height = second_height; - - try_delegate_to_gateway( - deps.as_mut(), - env1, - mock_info(delegation_owner1.as_str(), &vec![delegation1.clone()]), - identity.clone(), - ) - .unwrap(); - - assert_eq!( - RawDelegationData::new(delegation1.amount, initial_height), - gateway_delegations_read(&deps.storage, &identity) - .load(delegation_owner1.as_bytes()) - .unwrap() - ); - - try_delegate_to_gateway( - deps.as_mut(), - env2, - mock_info(delegation_owner2.as_str(), &vec![delegation2.clone()]), - identity.clone(), - ) - .unwrap(); - - assert_eq!( - RawDelegationData::new(delegation1.amount, initial_height), - gateway_delegations_read(&deps.storage, &identity) - .load(delegation_owner1.as_bytes()) - .unwrap() - ); - assert_eq!( - RawDelegationData::new(delegation2.amount, second_height), - gateway_delegations_read(&deps.storage, &identity) - .load(delegation_owner2.as_bytes()) - .unwrap() - ); - } - - #[test] - fn is_disallowed_for_already_delegated_node_if_it_unbonded() { - let mut deps = helpers::init_contract(); - - let gateway_owner = "bob"; - let identity = add_gateway(gateway_owner, good_gateway_bond(), &mut deps); - let delegation_owner = Addr::unchecked("sender"); - - try_delegate_to_gateway( - deps.as_mut(), - mock_env(), - mock_info(delegation_owner.as_str(), &coins(100, DENOM)), - identity.clone(), - ) - .unwrap(); - - try_remove_gateway(deps.as_mut(), mock_info(gateway_owner, &[])).unwrap(); - - assert_eq!( - Err(ContractError::GatewayBondNotFound { - identity: identity.clone() - }), - try_delegate_to_gateway( - deps.as_mut(), - mock_env(), - mock_info(delegation_owner.as_str(), &coins(50, DENOM)), - identity.clone() - ) - ); - } - - #[test] - fn is_allowed_for_multiple_nodes() { - let mut deps = helpers::init_contract(); - let gateway_owner1 = "bob"; - let gateway_owner2 = "fred"; - let identity1 = add_gateway(gateway_owner1, good_gateway_bond(), &mut deps); - let identity2 = add_gateway(gateway_owner2, good_gateway_bond(), &mut deps); - let delegation_owner = Addr::unchecked("sender"); - - assert!(try_delegate_to_gateway( - deps.as_mut(), - mock_env(), - mock_info(delegation_owner.as_str(), &coins(123, DENOM)), - identity1.clone() - ) - .is_ok()); - - assert!(try_delegate_to_gateway( - deps.as_mut(), - mock_env(), - mock_info(delegation_owner.as_str(), &coins(42, DENOM)), - identity2.clone() - ) - .is_ok()); - - assert_eq!( - RawDelegationData::new(123u128.into(), mock_env().block.height), - gateway_delegations_read(&deps.storage, &identity1) - .load(delegation_owner.as_bytes()) - .unwrap() - ); - assert!( - reverse_gateway_delegations_read(&deps.storage, &delegation_owner) - .load(identity1.as_bytes()) - .is_ok() - ); - - assert_eq!( - RawDelegationData::new(42u128.into(), mock_env().block.height), - gateway_delegations_read(&deps.storage, &identity2) - .load(delegation_owner.as_bytes()) - .unwrap() - ); - assert!( - reverse_gateway_delegations_read(&deps.storage, &delegation_owner) - .load(identity2.as_bytes()) - .is_ok() - ); - } - - #[test] - fn is_allowed_by_multiple_users() { - let mut deps = helpers::init_contract(); - let gateway_owner = "bob"; - let identity = add_gateway(gateway_owner, good_gateway_bond(), &mut deps); - - let delegation1 = coin(123, DENOM); - let delegation2 = coin(234, DENOM); - - assert!(try_delegate_to_gateway( - deps.as_mut(), - mock_env(), - mock_info("sender1", &vec![delegation1.clone()]), - identity.clone() - ) - .is_ok()); - - assert!(try_delegate_to_gateway( - deps.as_mut(), - mock_env(), - mock_info("sender2", &vec![delegation2.clone()]), - identity.clone() - ) - .is_ok()); - - // node's "total_delegation" is sum of both - assert_eq!( - delegation1.amount + delegation2.amount, - gateways_read(&deps.storage) - .load(identity.as_bytes()) - .unwrap() - .total_delegation - .amount - ) - } - - #[test] - fn delegation_is_not_removed_if_node_unbonded() { - let mut deps = helpers::init_contract(); - - let gateway_owner = "bob"; - let identity = add_gateway(gateway_owner, good_gateway_bond(), &mut deps); - let delegation_owner = Addr::unchecked("sender"); - - try_delegate_to_gateway( - deps.as_mut(), - mock_env(), - mock_info(delegation_owner.as_str(), &coins(100, DENOM)), - identity.clone(), - ) - .unwrap(); - - try_remove_gateway(deps.as_mut(), mock_info(gateway_owner, &[])).unwrap(); - - assert_eq!( - RawDelegationData::new(100u128.into(), mock_env().block.height), - gateway_delegations_read(&deps.storage, &identity) - .load(delegation_owner.as_bytes()) - .unwrap() - ); - assert!( - reverse_gateway_delegations_read(&deps.storage, &delegation_owner) - .load(identity.as_bytes()) - .is_ok() - ); - } - } - - #[cfg(test)] - mod removing_gateway_stake_delegation { - use super::*; - use crate::storage::gateway_delegations_read; - use crate::support::tests::helpers::add_gateway; - - #[test] - fn fails_if_delegation_never_existed() { - let mut deps = helpers::init_contract(); - - let gateway_owner = "bob"; - let identity = add_gateway(gateway_owner, good_gateway_bond(), &mut deps); - let delegation_owner = Addr::unchecked("sender"); - - assert_eq!( - Err(ContractError::NoGatewayDelegationFound { - identity: identity.clone(), - address: delegation_owner.clone(), - }), - try_remove_delegation_from_gateway( - deps.as_mut(), - mock_info(delegation_owner.as_str(), &[]), - identity, - ) - ); - } - - #[test] - fn succeeds_if_delegation_existed() { - let mut deps = helpers::init_contract(); - - let gateway_owner = "bob"; - let identity = add_gateway(gateway_owner, good_gateway_bond(), &mut deps); - let delegation_owner = Addr::unchecked("sender"); - - try_delegate_to_gateway( - deps.as_mut(), - mock_env(), - mock_info(delegation_owner.as_str(), &coins(100, DENOM)), - identity.clone(), - ) - .unwrap(); - - assert_eq!( - Ok(Response { - submessages: vec![], - messages: vec![BankMsg::Send { - to_address: delegation_owner.clone().into(), - amount: coins(100, DENOM), - } - .into()], - attributes: Vec::new(), - data: None, - }), - try_remove_delegation_from_gateway( - deps.as_mut(), - mock_info(delegation_owner.as_str(), &[]), - identity.clone(), - ) - ); - - assert!(gateway_delegations_read(&deps.storage, &identity) - .may_load(delegation_owner.as_bytes()) - .unwrap() - .is_none()); - assert!( - reverse_mix_delegations_read(&deps.storage, &delegation_owner) - .may_load(identity.as_bytes()) - .unwrap() - .is_none() - ); - - // and total delegation is cleared - assert_eq!( - Uint128::zero(), - gateways_read(&deps.storage) - .load(identity.as_bytes()) - .unwrap() - .total_delegation - .amount - ) - } - - #[test] - fn succeeds_if_delegation_existed_even_if_node_unbonded() { - let mut deps = helpers::init_contract(); - - let gateway_owner = "bob"; - let identity = add_gateway(gateway_owner, good_gateway_bond(), &mut deps); - let delegation_owner = Addr::unchecked("sender"); - - try_delegate_to_gateway( - deps.as_mut(), - mock_env(), - mock_info(delegation_owner.as_str(), &coins(100, DENOM)), - identity.clone(), - ) - .unwrap(); - - try_remove_gateway(deps.as_mut(), mock_info(gateway_owner, &[])).unwrap(); - - assert_eq!( - Ok(Response { - submessages: vec![], - messages: vec![BankMsg::Send { - to_address: delegation_owner.clone().into(), - amount: coins(100, DENOM), - } - .into()], - attributes: Vec::new(), - data: None, - }), - try_remove_delegation_from_gateway( - deps.as_mut(), - mock_info(delegation_owner.as_str(), &[]), - identity.clone(), - ) - ); - - assert!(gateway_delegations_read(&deps.storage, &identity) - .may_load(delegation_owner.as_bytes()) - .unwrap() - .is_none()); - assert!( - reverse_gateway_delegations_read(&deps.storage, &delegation_owner) - .may_load(identity.as_bytes()) - .unwrap() - .is_none() - ); - } - - #[test] - fn total_delegation_is_preserved_if_only_some_undelegate() { - let mut deps = helpers::init_contract(); - let gateway_owner = "bob"; - let identity = add_gateway(gateway_owner, good_gateway_bond(), &mut deps); - let delegation_owner1 = Addr::unchecked("sender1"); - let delegation_owner2 = Addr::unchecked("sender2"); - - let delegation1 = coin(123, DENOM); - let delegation2 = coin(234, DENOM); - - assert!(try_delegate_to_gateway( - deps.as_mut(), - mock_env(), - mock_info(delegation_owner1.as_str(), &vec![delegation1.clone()]), - identity.clone() - ) - .is_ok()); - - assert!(try_delegate_to_gateway( - deps.as_mut(), - mock_env(), - mock_info(delegation_owner2.as_str(), &vec![delegation2.clone()]), - identity.clone() - ) - .is_ok()); - - // sender1 undelegates - try_remove_delegation_from_gateway( - deps.as_mut(), - mock_info(delegation_owner1.as_str(), &[]), - identity.clone(), - ) - .unwrap(); - - // but total delegation should still equal to what sender2 sent - // node's "total_delegation" is sum of both - assert_eq!( - delegation2, - gateways_read(&deps.storage) - .load(identity.as_bytes()) - .unwrap() - .total_delegation - ) - } - } - - #[test] - fn delegators_on_gateway_reward_rate() { - let mut deps = helpers::init_contract(); - let mut env = mock_env(); - let current_state = config(deps.as_mut().storage).load().unwrap(); - let network_monitor_address = current_state.network_monitor_address; - - let initial_gateway_bond = 100_000000; - let initial_delegation1 = 50000; // will see single digits rewards - let initial_delegation2 = 100; // won't see any rewards due to such a small delegation - let initial_delegation3 = 100000_000000; // will see big proper rewards - - let node_owner = "node-owner"; - let identity = add_gateway(node_owner, good_gateway_bond(), &mut deps); - - gateway_delegations(&mut deps.storage, &identity) - .save(b"delegator1", &raw_delegation_fixture(initial_delegation1)) - .unwrap(); - gateway_delegations(&mut deps.storage, &identity) - .save(b"delegator2", &raw_delegation_fixture(initial_delegation2)) - .unwrap(); - gateway_delegations(&mut deps.storage, &identity) - .save(b"delegator3", &raw_delegation_fixture(initial_delegation3)) - .unwrap(); - - env.block.height += 2 * MINIMUM_BLOCK_AGE_FOR_REWARDING; - - let bond_reward = read_gateway_epoch_bond_reward_rate(deps.as_ref().storage); - let delegation_reward = read_gateway_epoch_delegation_reward_rate(deps.as_ref().storage); - - // the node's bond and delegations are correctly increased and scaled by uptime - // if node was 100% up, it will get full epoch reward - let expected_gateway_reward = Uint128(initial_gateway_bond) * bond_reward; - let expected_delegation1_reward = Uint128(initial_delegation1) * delegation_reward; - let expected_delegation2_reward = Uint128(initial_delegation2) * delegation_reward; - let expected_delegation3_reward = Uint128(initial_delegation3) * delegation_reward; - - let expected_bond = expected_gateway_reward + Uint128(initial_gateway_bond); - let expected_delegation1 = expected_delegation1_reward + Uint128(initial_delegation1); - let expected_delegation2 = expected_delegation2_reward + Uint128(initial_delegation2); - let expected_delegation3 = expected_delegation3_reward + Uint128(initial_delegation3); - - let info = mock_info(network_monitor_address.as_ref(), &[]); - let res = - try_reward_gateway(deps.as_mut(), env.clone(), info, identity.clone(), 100).unwrap(); - - assert_eq!( - expected_bond, - read_gateway_bond(deps.as_ref().storage, identity.as_bytes()).unwrap() - ); - - assert_eq!( - expected_delegation1, - gateway_delegations_read(deps.as_ref().storage, &identity) - .load("delegator1".as_bytes()) - .unwrap() - .amount - ); - - assert_eq!( - expected_delegation2, - gateway_delegations_read(deps.as_ref().storage, &identity) - .load("delegator2".as_bytes()) - .unwrap() - .amount - ); - - assert_eq!( - expected_delegation3, - gateway_delegations_read(deps.as_ref().storage, &identity) - .load("delegator3".as_bytes()) - .unwrap() - .amount - ); - - assert_eq!( - vec![ - attr("bond increase", expected_gateway_reward), - attr( - "total delegation increase", - expected_delegation1_reward - + expected_delegation2_reward - + expected_delegation3_reward - ), - ], - res.attributes - ); - - // if node was 20% up, it will get 1/5th of epoch reward - let scaled_bond_reward = scale_reward_by_uptime(bond_reward, 20).unwrap(); - let scaled_delegation_reward = scale_reward_by_uptime(delegation_reward, 20).unwrap(); - - let expected_gateway_reward = expected_bond * scaled_bond_reward; - let expected_delegation1_reward = expected_delegation1 * scaled_delegation_reward; - let expected_delegation2_reward = expected_delegation2 * scaled_delegation_reward; - let expected_delegation3_reward = expected_delegation3 * scaled_delegation_reward; - - let expected_bond = expected_gateway_reward + expected_bond; - let expected_delegation1 = expected_delegation1_reward + expected_delegation1; - let expected_delegation2 = expected_delegation2_reward + expected_delegation2; - let expected_delegation3 = expected_delegation3_reward + expected_delegation3; - - let info = mock_info(network_monitor_address.as_ref(), &[]); - let res = - try_reward_gateway(deps.as_mut(), env.clone(), info, identity.clone(), 20).unwrap(); - - assert_eq!( - expected_bond, - read_gateway_bond(deps.as_ref().storage, identity.as_bytes()).unwrap() - ); - - assert_eq!( - expected_delegation1, - gateway_delegations_read(deps.as_ref().storage, &identity) - .load("delegator1".as_bytes()) - .unwrap() - .amount - ); - - assert_eq!( - expected_delegation2, - gateway_delegations_read(deps.as_ref().storage, &identity) - .load("delegator2".as_bytes()) - .unwrap() - .amount - ); - - assert_eq!( - expected_delegation3, - gateway_delegations_read(deps.as_ref().storage, &identity) - .load("delegator3".as_bytes()) - .unwrap() - .amount - ); - - assert_eq!( - vec![ - attr("bond increase", expected_gateway_reward), - attr( - "total delegation increase", - expected_delegation1_reward - + expected_delegation2_reward - + expected_delegation3_reward - ), - ], - res.attributes - ); - - // if the node was 0% up, nobody will get any rewards - let info = mock_info(network_monitor_address.as_ref(), &[]); - let res = - try_reward_gateway(deps.as_mut(), env.clone(), info, identity.clone(), 0).unwrap(); - - assert_eq!( - expected_bond, - read_gateway_bond(deps.as_ref().storage, identity.as_bytes()).unwrap() - ); - - assert_eq!( - expected_delegation1, - gateway_delegations_read(deps.as_ref().storage, &identity) - .load("delegator1".as_bytes()) - .unwrap() - .amount - ); - - assert_eq!( - expected_delegation2, - gateway_delegations_read(deps.as_ref().storage, &identity) - .load("delegator2".as_bytes()) - .unwrap() - .amount - ); - - assert_eq!( - expected_delegation3, - gateway_delegations_read(deps.as_ref().storage, &identity) - .load("delegator3".as_bytes()) - .unwrap() - .amount - ); - - assert_eq!( - vec![ - attr("bond increase", Uint128(0)), - attr("total delegation increase", Uint128(0)), - ], - res.attributes - ); - } - #[test] fn multiple_page_delegations() { let mut deps = helpers::init_contract(); @@ -3911,19 +2577,6 @@ pub mod tests { DELEGATION_PAGE_DEFAULT_LIMIT * 10, mix_delegations.len() as u32 ); - - store_n_gateway_delegations( - DELEGATION_PAGE_DEFAULT_LIMIT * 10, - &mut deps.storage, - &node_identity, - ); - let gateway_bucket = all_gateway_delegations_read::(&deps.storage); - let gateway_delegations = Delegations::new(gateway_bucket) - .collect::>>(); - assert_eq!( - DELEGATION_PAGE_DEFAULT_LIMIT * 10, - gateway_delegations.len() as u32 - ); } #[cfg(test)] diff --git a/tauri-wallet/src-tauri/src/main.rs b/tauri-wallet/src-tauri/src/main.rs index 79463f63a4..8ac9f6c423 100644 --- a/tauri-wallet/src-tauri/src/main.rs +++ b/tauri-wallet/src-tauri/src/main.rs @@ -58,15 +58,12 @@ fn main() { unbond_gateway, delegate_to_mixnode, undelegate_from_mixnode, - delegate_to_gateway, - undelegate_from_gateway, send, create_new_account, get_fee, get_state_params, update_state_params, get_reverse_mix_delegations_paged, - get_reverse_gateway_delegations_paged, ]) .menu(create_menu_items()) .run(tauri::generate_context!()) diff --git a/tauri-wallet/src-tauri/src/operations/admin.rs b/tauri-wallet/src-tauri/src/operations/admin.rs index 2d3ad52ae7..71ac69af8a 100644 --- a/tauri-wallet/src-tauri/src/operations/admin.rs +++ b/tauri-wallet/src-tauri/src/operations/admin.rs @@ -16,11 +16,8 @@ pub struct TauriStateParams { minimum_mixnode_bond: String, minimum_gateway_bond: String, mixnode_bond_reward_rate: String, - gateway_bond_reward_rate: String, mixnode_delegation_reward_rate: String, - gateway_delegation_reward_rate: String, mixnode_active_set_size: u32, - gateway_active_set_size: u32, } impl From for TauriStateParams { @@ -30,11 +27,8 @@ impl From for TauriStateParams { minimum_mixnode_bond: p.minimum_mixnode_bond.to_string(), minimum_gateway_bond: p.minimum_gateway_bond.to_string(), mixnode_bond_reward_rate: p.mixnode_bond_reward_rate.to_string(), - gateway_bond_reward_rate: p.gateway_bond_reward_rate.to_string(), mixnode_delegation_reward_rate: p.mixnode_delegation_reward_rate.to_string(), - gateway_delegation_reward_rate: p.gateway_delegation_reward_rate.to_string(), mixnode_active_set_size: p.mixnode_active_set_size, - gateway_active_set_size: p.gateway_active_set_size, } } } @@ -48,11 +42,8 @@ impl TryFrom for StateParams { minimum_mixnode_bond: Uint128::try_from(p.minimum_mixnode_bond.as_str())?, minimum_gateway_bond: Uint128::try_from(p.minimum_gateway_bond.as_str())?, mixnode_bond_reward_rate: Decimal::from_str(p.mixnode_bond_reward_rate.as_str())?, - gateway_bond_reward_rate: Decimal::from_str(p.gateway_bond_reward_rate.as_str())?, mixnode_delegation_reward_rate: Decimal::from_str(p.mixnode_delegation_reward_rate.as_str())?, - gateway_delegation_reward_rate: Decimal::from_str(p.gateway_delegation_reward_rate.as_str())?, mixnode_active_set_size: p.mixnode_active_set_size, - gateway_active_set_size: p.gateway_active_set_size, }) } } diff --git a/tauri-wallet/src-tauri/src/operations/delegate.rs b/tauri-wallet/src-tauri/src/operations/delegate.rs index bba966ebec..a9c9a75269 100644 --- a/tauri-wallet/src-tauri/src/operations/delegate.rs +++ b/tauri-wallet/src-tauri/src/operations/delegate.rs @@ -2,9 +2,7 @@ use crate::coin::Coin; use crate::format_err; use crate::state::State; use cosmwasm_std::Coin as CosmWasmCoin; -use mixnet_contract::{ - Addr, PagedReverseGatewayDelegationsResponse, PagedReverseMixDelegationsResponse, -}; +use mixnet_contract::{Addr, PagedReverseMixDelegationsResponse}; use serde::{Deserialize, Serialize}; use std::convert::TryInto; use std::sync::Arc; @@ -57,45 +55,6 @@ pub async fn undelegate_from_mixnode( } } -#[tauri::command] -pub async fn delegate_to_gateway( - identity: &str, - amount: Coin, - state: tauri::State<'_, Arc>>, -) -> Result { - let r_state = state.read().await; - let bond: CosmWasmCoin = match amount.try_into() { - Ok(b) => b, - Err(e) => return Err(format_err!(e)), - }; - let client = r_state.client()?; - match client.delegate_to_gateway(identity, &bond).await { - Ok(_result) => Ok(DelegationResult { - source_address: client.address().to_string(), - target_address: identity.to_string(), - amount: Some(bond.into()), - }), - Err(e) => Err(format_err!(e)), - } -} - -#[tauri::command] -pub async fn undelegate_from_gateway( - identity: &str, - state: tauri::State<'_, Arc>>, -) -> Result { - let r_state = state.read().await; - let client = r_state.client()?; - match client.remove_gateway_delegation(identity).await { - Ok(_result) => Ok(DelegationResult { - source_address: client.address().to_string(), - target_address: identity.to_string(), - amount: None, - }), - Err(e) => Err(format_err!(e)), - } -} - #[tauri::command] pub async fn get_reverse_mix_delegations_paged( state: tauri::State<'_, Arc>>, @@ -104,16 +63,6 @@ pub async fn get_reverse_mix_delegations_paged( let client = r_state.client()?; client .get_reverse_mix_delegations_paged(Addr::unchecked(client.address().as_ref()), None, None) - .await.map_err(|err| format_err!(err)) -} - -#[tauri::command] -pub async fn get_reverse_gateway_delegations_paged( - state: tauri::State<'_, Arc>>, -) -> Result { - let r_state = state.read().await; - let client = r_state.client()?; - client - .get_reverse_gateway_delegations_paged(Addr::unchecked(client.address().as_ref()), None, None) - .await.map_err(|err| format_err!(err)) + .await + .map_err(|err| format_err!(err)) } diff --git a/tauri-wallet/src/types/rust/stateparams.ts b/tauri-wallet/src/types/rust/stateparams.ts index b7dbabc531..4f6a8c6eea 100644 --- a/tauri-wallet/src/types/rust/stateparams.ts +++ b/tauri-wallet/src/types/rust/stateparams.ts @@ -3,9 +3,6 @@ export interface TauriStateParams { minimum_mixnode_bond: string; minimum_gateway_bond: string; mixnode_bond_reward_rate: string; - gateway_bond_reward_rate: string; mixnode_delegation_reward_rate: string; - gateway_delegation_reward_rate: string; mixnode_active_set_size: number; - gateway_active_set_size: number; } \ No newline at end of file diff --git a/validator-api/migrations/20211101110000_no_gateway_rewarding.sql b/validator-api/migrations/20211101110000_no_gateway_rewarding.sql new file mode 100644 index 0000000000..542ef02b3e --- /dev/null +++ b/validator-api/migrations/20211101110000_no_gateway_rewarding.sql @@ -0,0 +1,25 @@ +/* + * Copyright 2021 - Nym Technologies SA + * SPDX-License-Identifier: Apache-2.0 + */ + +ALTER TABLE rewarding_report RENAME TO _rewarding_report_old; + +CREATE TABLE rewarding_report +( + epoch_rewarding_id INTEGER NOT NULL, + + eligible_mixnodes INTEGER NOT NULL, + + possibly_unrewarded_mixnodes INTEGER NOT NULL, + + FOREIGN KEY (epoch_rewarding_id) REFERENCES epoch_rewarding (id) +); + +INSERT INTO rewarding_report (epoch_rewarding_id, eligible_mixnodes, possibly_unrewarded_mixnodes) +SELECT epoch_rewarding_id, eligible_mixnodes, possibly_unrewarded_mixnodes +FROM _rewarding_report_old; + +DROP TABLE _rewarding_report_old; +DROP TABLE failed_gateway_reward_chunk; +DROP TABLE possibly_unrewarded_gateway; \ No newline at end of file diff --git a/validator-api/src/cache/mod.rs b/validator-api/src/cache/mod.rs index dfa4424659..7a1cf9864b 100644 --- a/validator-api/src/cache/mod.rs +++ b/validator-api/src/cache/mod.rs @@ -33,10 +33,7 @@ struct ValidatorCacheInner { gateways: RwLock>>, active_mixnodes_available: AtomicBool, - active_gateways_available: AtomicBool, - current_mixnode_active_set_size: AtomicUsize, - current_gateway_active_set_size: AtomicUsize, } #[derive(Default, Serialize, Clone)] @@ -131,7 +128,6 @@ impl ValidatorCache { routes::get_mixnodes, routes::get_gateways, routes::get_active_mixnodes, - routes::get_active_gateways ], ) }) @@ -155,28 +151,10 @@ impl ValidatorCache { true } - // TODO: check if all nodes can be compared together, - // i.e. they all have the same denom for bonds and delegations - fn verify_gateways(&self, gateways: &[GatewayBond]) -> bool { - if gateways.is_empty() { - return true; - } - let expected_denom = &gateways[0].bond_amount.denom; - for gateway in gateways { - if &gateway.bond_amount.denom != expected_denom - || &gateway.total_delegation.denom != expected_denom - { - return false; - } - } - - true - } - async fn update_cache( &self, mut mixnodes: Vec, - mut gateways: Vec, + gateways: Vec, state: StateParams, ) { // if our data is valid, it means the active sets are available, @@ -199,23 +177,6 @@ impl ValidatorCache { .store(false, Ordering::SeqCst); } - if self.verify_gateways(&gateways) { - // partial_cmp can only fail if the nodes have different denomination, - // but we just checked for that hence the unwraps are fine here - // Note the reverse order of comparison so that the "highest" node would be first - gateways.sort_by(|a, b| b.partial_cmp(a).unwrap()); - self.inner - .active_gateways_available - .store(true, Ordering::SeqCst); - self.inner - .current_gateway_active_set_size - .store(state.gateway_active_set_size as usize, Ordering::SeqCst); - } else { - self.inner - .active_gateways_available - .store(false, Ordering::SeqCst); - } - self.inner.mixnodes.write().await.set(mixnodes); self.inner.gateways.write().await.set(gateways); } @@ -252,30 +213,6 @@ impl ValidatorCache { } } - pub async fn active_gateways(&self) -> Option>> { - // if active set is available, it means it is already sorted - if self.inner.active_gateways_available.load(Ordering::SeqCst) { - let cache = self.inner.gateways.read().await; - let timestamp = cache.as_at; - let nodes = cache - .value - .iter() - .take( - self.inner - .current_gateway_active_set_size - .load(Ordering::SeqCst), - ) - .cloned() - .collect(); - Some(Cache { - value: nodes, - as_at: timestamp, - }) - } else { - None - } - } - pub fn initialised(&self) -> bool { self.inner.initialised.load(Ordering::Relaxed) } @@ -300,9 +237,7 @@ impl ValidatorCacheInner { mixnodes: RwLock::new(Cache::default()), gateways: RwLock::new(Cache::default()), active_mixnodes_available: AtomicBool::new(false), - active_gateways_available: AtomicBool::new(false), current_mixnode_active_set_size: Default::default(), - current_gateway_active_set_size: Default::default(), } } } diff --git a/validator-api/src/cache/routes.rs b/validator-api/src/cache/routes.rs index a076aac4ac..c3e3c858aa 100644 --- a/validator-api/src/cache/routes.rs +++ b/validator-api/src/cache/routes.rs @@ -22,10 +22,3 @@ pub(crate) async fn get_active_mixnodes( ) -> Option>> { cache.active_mixnodes().await.map(|cache| Json(cache.value)) } - -#[get("/gateways/active")] -pub(crate) async fn get_active_gateways( - cache: &State, -) -> Option>> { - cache.active_gateways().await.map(|cache| Json(cache.value)) -} diff --git a/validator-api/src/nymd_client.rs b/validator-api/src/nymd_client.rs index 1205736433..38dbd1e488 100644 --- a/validator-api/src/nymd_client.rs +++ b/validator-api/src/nymd_client.rs @@ -3,8 +3,7 @@ use crate::config::Config; use crate::rewarding::{ - error::RewardingError, GatewayToReward, MixnodeToReward, GATEWAY_REWARD_OP_BASE_GAS_LIMIT, - MIXNODE_REWARD_OP_BASE_GAS_LIMIT, PER_GATEWAY_DELEGATION_GAS_INCREASE, + error::RewardingError, MixnodeToReward, MIXNODE_REWARD_OP_BASE_GAS_LIMIT, PER_MIXNODE_DELEGATION_GAS_INCREASE, REWARDING_GAS_LIMIT_MULTIPLIER, }; use config::defaults::DEFAULT_VALIDATOR_API_PORT; @@ -129,20 +128,6 @@ impl Client { .await } - pub(crate) async fn get_gateway_delegations( - &self, - identity: IdentityKey, - ) -> Result, ValidatorClientError> - where - C: CosmWasmClient + Sync, - { - self.0 - .read() - .await - .get_all_nymd_single_gateway_delegations(identity) - .await - } - async fn estimate_mixnode_reward_fees(&self, nodes: usize, total_delegations: usize) -> Fee { let base_gas_limit = MIXNODE_REWARD_OP_BASE_GAS_LIMIT * nodes as u64 + PER_MIXNODE_DELEGATION_GAS_INCREASE * total_delegations as u64; @@ -156,19 +141,6 @@ impl Client { .calculate_custom_fee(total_gas_limit) } - async fn estimate_gateway_reward_fees(&self, nodes: usize, total_delegations: usize) -> Fee { - let base_gas_limit = GATEWAY_REWARD_OP_BASE_GAS_LIMIT * nodes as u64 - + PER_GATEWAY_DELEGATION_GAS_INCREASE * total_delegations as u64; - - let total_gas_limit = (base_gas_limit as f64 * REWARDING_GAS_LIMIT_MULTIPLIER) as u64; - - self.0 - .read() - .await - .nymd - .calculate_custom_fee(total_gas_limit) - } - pub(crate) async fn reward_mixnodes( &self, nodes: &[MixnodeToReward], @@ -236,72 +208,4 @@ impl Client { } } } - - pub(crate) async fn reward_gateways( - &self, - nodes: &[GatewayToReward], - ) -> Result<(), RewardingError> - where - C: SigningCosmWasmClient + Sync, - { - let total_delegations = nodes.iter().map(|node| node.total_delegations).sum(); - let fee = self - .estimate_gateway_reward_fees(nodes.len(), total_delegations) - .await; - let msgs: Vec<(ExecuteMsg, _)> = nodes - .iter() - .map(Into::into) - .zip(std::iter::repeat(Vec::new())) - .collect(); - - let memo = format!("rewarding {} gateways", msgs.len()); - - let contract = self - .0 - .read() - .await - .get_mixnet_contract_address() - .ok_or(RewardingError::UnspecifiedContractAddress)?; - - // grab the write lock here so we're sure nothing else is executing anything on the contract - // in the meantime - // however, we're not 100% guarded against everything - // for example somebody might have taken the mnemonic used by the validator - // and sent a transaction manually using the same account. The sequence number - // would have gotten incremented, yet the rewarding transaction might have actually not - // been included in the block. sadly we can't do much about that. - let client_guard = self.0.write().await; - let pre_sequence = client_guard.nymd.account_sequence().await?; - - let res = client_guard - .nymd - .execute_multiple(&contract, msgs.clone(), fee.clone(), memo.clone()) - .await; - - match res { - Ok(_) => Ok(()), - Err(err) => { - if err.is_tendermint_response_timeout() { - // wait until we're sure we're into the next block (remember we're holding the lock) - sleep(Duration::from_secs(11)).await; - let curr_sequence = client_guard.nymd.account_sequence().await?; - if curr_sequence.sequence > pre_sequence.sequence { - // unless somebody was messing around doing stuff manually in that tiny time interval - // we're good. It was a false negative. - Ok(()) - } else { - // the sequence number has not increased, meaning the transaction was not executed - // so attempt to send it again - client_guard - .nymd - .execute_multiple(&contract, msgs, fee, memo) - .await?; - Ok(()) - } - } else { - Err(err.into()) - } - } - } - } } diff --git a/validator-api/src/rewarding/error.rs b/validator-api/src/rewarding/error.rs index 1e54cb48b1..7cd544868f 100644 --- a/validator-api/src/rewarding/error.rs +++ b/validator-api/src/rewarding/error.rs @@ -14,9 +14,6 @@ pub(crate) enum RewardingError { #[error("There were no mixnodes to reward (network is dead)")] NoMixnodesToReward, - #[error("There were no gateways to reward (network is dead)")] - NoGatewaysToReward, - #[error("Failed to execute the smart contract - {0}")] ContractExecutionFailure(NymdError), diff --git a/validator-api/src/rewarding/mod.rs b/validator-api/src/rewarding/mod.rs index 2e0c3b135e..ba6d33cd29 100644 --- a/validator-api/src/rewarding/mod.rs +++ b/validator-api/src/rewarding/mod.rs @@ -8,8 +8,7 @@ use crate::nymd_client::Client; use crate::rewarding::epoch::Epoch; use crate::rewarding::error::RewardingError; use crate::storage::models::{ - FailedGatewayRewardChunk, FailedMixnodeRewardChunk, PossiblyUnrewardedGateway, - PossiblyUnrewardedMixnode, RewardingReport, + FailedMixnodeRewardChunk, PossiblyUnrewardedMixnode, RewardingReport, }; use crate::storage::NodeStatusStorage; use log::{error, info}; @@ -27,7 +26,6 @@ pub(crate) mod error; // the actual base cost is around 125_000, but let's give ourselves a bit of safety net in case // we introduce some tiny contract changes that would bump that value up pub(crate) const MIXNODE_REWARD_OP_BASE_GAS_LIMIT: u64 = 150_000; -pub(crate) const GATEWAY_REWARD_OP_BASE_GAS_LIMIT: u64 = 150_000; // For each delegation reward we perform a read and a write is being executed, // which are the most costly parts involved in process. Both of them are ~1000 sdk gas in cost. @@ -36,7 +34,6 @@ pub(crate) const GATEWAY_REWARD_OP_BASE_GAS_LIMIT: u64 = 150_000; // Therefore, since base cost is not tuned to the bare minimum, let's treat all of delegations as extra // 2750 of sdk gas. pub(crate) const PER_MIXNODE_DELEGATION_GAS_INCREASE: u64 = 2750; -pub(crate) const PER_GATEWAY_DELEGATION_GAS_INCREASE: u64 = 2750; // Another safety net in case of contract changes, // the calculated total gas limit is going to get multiplied by that value. @@ -53,29 +50,14 @@ pub(crate) struct MixnodeToReward { pub(crate) total_delegations: usize, } -#[derive(Debug, Clone)] -pub(crate) struct GatewayToReward { - pub(crate) identity: IdentityKey, - pub(crate) uptime: Uptime, - - /// Total number of individual addresses that have delegated to this particular gateway - pub(crate) total_delegations: usize, -} - pub(crate) struct FailedMixnodeRewardChunkDetails { possibly_unrewarded: Vec, error_message: String, } -pub(crate) struct FailedGatewayRewardChunkDetails { - possibly_unrewarded: Vec, - error_message: String, -} - #[derive(Default)] pub(crate) struct FailureData { mixnodes: Option>, - gateways: Option>, } impl<'a> From<&'a MixnodeToReward> for ExecuteMsg { @@ -87,15 +69,6 @@ impl<'a> From<&'a MixnodeToReward> for ExecuteMsg { } } -impl<'a> From<&'a GatewayToReward> for ExecuteMsg { - fn from(node: &GatewayToReward) -> Self { - ExecuteMsg::RewardGateway { - identity: node.identity.clone(), - uptime: node.uptime.u8() as u32, - } - } -} - pub(crate) struct Rewarder { nymd_client: Client, validator_cache: ValidatorCache, @@ -149,22 +122,6 @@ impl Rewarder { .len()) } - /// Obtains the current number of delegators that have delegated their stake towards this particular gateway. - /// - /// # Arguments - /// - /// * `identity`: identity key of the gateway - async fn get_gateway_delegators_count( - &self, - identity: IdentityKey, - ) -> Result { - Ok(self - .nymd_client - .get_gateway_delegations(identity) - .await? - .len()) - } - /// Queries the smart contract in order to obtain the current list of bonded mixnodes and then /// for each mixnode determines how many delegators it has. async fn produce_active_mixnode_delegators_map( @@ -202,30 +159,6 @@ impl Rewarder { Ok(map) } - /// Queries the smart contract in order to obtain the current list of bonded gateways and then - /// for each gateway determines how many delegators it has. - async fn produce_active_gateway_delegators_map( - &self, - ) -> Result, RewardingError> { - // look at comments in `produce_mixnode_delegators_map` for some optimisation elaboration - let mut map = HashMap::new(); - - let active_bonded_gateways = self - .validator_cache - .active_gateways() - .await - .ok_or(RewardingError::NoGatewaysToReward)? - .into_inner(); - for gateway in active_bonded_gateways.into_iter() { - let delegator_count = self - .get_gateway_delegators_count(gateway.gateway.identity_key.clone()) - .await?; - map.insert(gateway.gateway.identity_key, delegator_count); - } - - Ok(map) - } - /// Calculates the absolute uptime of given node that is then passed as one of the arguments /// in the smart contract to determine the actual reward value. /// @@ -290,46 +223,6 @@ impl Rewarder { Ok(eligible_nodes) } - /// Given the list of gateways that were tested in the last epoch, tries to determine the - /// subset that are eligible for any rewards. - /// - /// As of right now, it is a rather straightforward process. It is checked whether the node - /// is currently bonded, has uptime > 0 and is part of the "active" set. - /// Unlike the typescript rewards script, it currently does not look at the non-mixing ports are open. - /// - /// The method also obtains the number of delegators towards the node in order to more accurately - /// approximate the required gas fees when distributing the rewards. - /// - /// # Arguments - /// - /// * `active_gateways`: list of the nodes that were tested at least once by the network monitor - /// in the last epoch. - async fn determine_eligible_gateways( - &self, - active_gateways: &[GatewayStatusReport], - ) -> Result, RewardingError> { - let gateway_delegators = self.produce_active_gateway_delegators_map().await?; - - let eligible_nodes = active_gateways - .iter() - .filter_map(|gateway| { - gateway_delegators - .get(&gateway.identity) - .map(|&total_delegations| GatewayToReward { - identity: gateway.identity.clone(), - uptime: self.calculate_absolute_uptime( - gateway.last_day_ipv4, - gateway.last_day_ipv6, - ), - total_delegations, - }) - }) - .filter(|node| node.uptime.u8() > 0) - .collect(); - - Ok(eligible_nodes) - } - /// Obtains the lists of all mixnodes and gateways that were tested at least a single time /// by the network monitor in the specified epoch. /// @@ -410,58 +303,6 @@ impl Rewarder { } } - /// Using the list of gateways eligible for rewards, chunks it into pre-defined sized-chunks - /// and gives out the rewards by calling the smart contract. - /// - /// Returns an optional vector containing list of chunks that experienced a smart contract - /// execution error during reward distribution. However, it does not necessarily imply they - /// were not rewarded. There are some edge cases where we time out waiting for block to be included - /// yet the transactions went through. - /// - /// Only returns errors for problems originating from before smart contract was called, i.e. - /// we know for sure not a single node has been rewarded. - /// - /// # Arguments - /// - /// * `eligible_gateways`: list of the nodes that are eligible to receive non-zero rewards. - async fn distribute_rewards_to_gateways( - &self, - eligible_gateways: &[GatewayToReward], - ) -> Option> { - let mut failed_chunks = Vec::new(); - - for (i, gateway_chunk) in eligible_gateways.chunks(MAX_TO_REWARD_AT_ONCE).enumerate() { - if let Err(err) = self.nymd_client.reward_gateways(gateway_chunk).await { - // this is a super weird edge case that we didn't catch change to sequence and - // resent rewards unnecessarily, but the mempool saved us from executing it again - // however, still we want to wait until we're sure we're into the next block - if !err.is_tendermint_duplicate() { - error!("failed to reward gateways... - {}", err); - failed_chunks.push(FailedGatewayRewardChunkDetails { - possibly_unrewarded: gateway_chunk.to_vec(), - error_message: err.to_string(), - }); - } - sleep(Duration::from_secs(11)).await; - } - - let rewarded = i * MAX_TO_REWARD_AT_ONCE + gateway_chunk.len(); - let percentage = rewarded as f32 * 100.0 / eligible_gateways.len() as f32; - info!( - "Rewarded {} / {} gateways\t{:.2}%", - rewarded, - eligible_gateways.len(), - percentage - ); - } - - if failed_chunks.is_empty() { - None - } else { - Some(failed_chunks) - } - } - /// Using the list of active mixnode and gateways, determine which of them are eligible for /// rewarding and distribute the rewards. /// @@ -471,14 +312,10 @@ impl Rewarder { /// /// * `active_monitor_mixnodes`: list of the nodes that were tested at least once by the network monitor /// in the last epoch. - /// - /// * `active_monitor_gateways`: list of the nodes that were tested at least once by the network monitor - /// in the last epoch. async fn distribute_rewards( &self, epoch_rewarding_id: i64, active_monitor_mixnodes: &[MixnodeStatusReport], - active_monitor_gateways: &[GatewayStatusReport], ) -> Result<(RewardingReport, Option), RewardingError> { let mut failure_data = FailureData::default(); @@ -489,25 +326,13 @@ impl Rewarder { return Err(RewardingError::NoMixnodesToReward); } - let eligible_gateways = self - .determine_eligible_gateways(active_monitor_gateways) - .await?; - if eligible_gateways.is_empty() { - return Err(RewardingError::NoGatewaysToReward); - } - failure_data.mixnodes = self .distribute_rewards_to_mixnodes(&eligible_mixnodes) .await; - failure_data.gateways = self - .distribute_rewards_to_gateways(&eligible_gateways) - .await; - let report = RewardingReport { epoch_rewarding_id, eligible_mixnodes: eligible_mixnodes.len() as i64, - eligible_gateways: eligible_gateways.len() as i64, possibly_unrewarded_mixnodes: failure_data .mixnodes .as_ref() @@ -518,19 +343,9 @@ impl Rewarder { .sum::() as i64 }) .unwrap_or_default(), - possibly_unrewarded_gateways: failure_data - .gateways - .as_ref() - .map(|chunks| { - chunks - .iter() - .map(|chunk| chunk.possibly_unrewarded.len()) - .sum::() as i64 - }) - .unwrap_or_default(), }; - if failure_data.mixnodes.is_none() && failure_data.gateways.is_none() { + if failure_data.mixnodes.is_none() { Ok((report, None)) } else { Ok((report, Some(failure_data))) @@ -575,30 +390,6 @@ impl Rewarder { } } - if let Some(failed_gateway_chunks) = failure_data.gateways { - for failed_chunk in failed_gateway_chunks.into_iter() { - // save the chunk - let chunk_id = self - .storage - .insert_failed_gateway_reward_chunk(FailedGatewayRewardChunk { - epoch_rewarding_id, - error_message: failed_chunk.error_message, - }) - .await?; - - // and then all associated nodes - for node in failed_chunk.possibly_unrewarded.into_iter() { - self.storage - .insert_possibly_unrewarded_gateway(PossiblyUnrewardedGateway { - chunk_id, - identity: node.identity, - uptime: node.uptime.u8(), - }) - .await?; - } - } - } - Ok(()) } @@ -731,11 +522,7 @@ impl Rewarder { .await?; let (report, failure_data) = self - .distribute_rewards( - epoch_rewarding_id, - &active_monitor_mixnodes, - &active_monitor_gateways, - ) + .distribute_rewards(epoch_rewarding_id, &active_monitor_mixnodes) .await?; self.storage diff --git a/validator-api/src/storage/manager.rs b/validator-api/src/storage/manager.rs index 28758f3594..a31816f45e 100644 --- a/validator-api/src/storage/manager.rs +++ b/validator-api/src/storage/manager.rs @@ -5,8 +5,8 @@ use crate::network_monitor::monitor::summary_producer::NodeResult; use crate::node_status_api::models::{HistoricalUptime, Uptime}; use crate::node_status_api::utils::ActiveNodeDayStatuses; use crate::storage::models::{ - ActiveNode, EpochRewarding, FailedGatewayRewardChunk, FailedMixnodeRewardChunk, NodeStatus, - PossiblyUnrewardedGateway, PossiblyUnrewardedMixnode, RewardingReport, + ActiveNode, EpochRewarding, FailedMixnodeRewardChunk, NodeStatus, PossiblyUnrewardedMixnode, + RewardingReport, }; use crate::storage::UnixTimestamp; use std::convert::TryFrom; @@ -791,17 +791,15 @@ impl StorageManager { sqlx::query!( r#" INSERT INTO rewarding_report - (epoch_rewarding_id, eligible_mixnodes, eligible_gateways, possibly_unrewarded_mixnodes, possibly_unrewarded_gateways) - VALUES (?, ?, ?, ?, ?); + (epoch_rewarding_id, eligible_mixnodes, possibly_unrewarded_mixnodes) + VALUES (?, ?, ?); "#, report.epoch_rewarding_id, report.eligible_mixnodes, - report.eligible_gateways, report.possibly_unrewarded_mixnodes, - report.possibly_unrewarded_gateways, ) - .execute(&self.connection_pool) - .await?; + .execute(&self.connection_pool) + .await?; Ok(()) } @@ -826,27 +824,6 @@ impl StorageManager { Ok(res.last_insert_rowid()) } - /// Inserts new failed gateway reward chunk information into the database. - /// Returns id of the newly created entry. - /// - /// # Arguments - /// - /// * `failed_chunk`: chunk information to insert. - pub(super) async fn insert_failed_gateway_reward_chunk( - &self, - failed_chunk: FailedGatewayRewardChunk, - ) -> Result { - let res = sqlx::query!( - r#" - INSERT INTO failed_gateway_reward_chunk (error_message, reward_summary_id) VALUES (?, ?) - "#, - failed_chunk.error_message, - failed_chunk.epoch_rewarding_id, - ).execute(&self.connection_pool).await?; - - Ok(res.last_insert_rowid()) - } - /// Inserts information into the database about a mixnode that might have been unfairly unrewarded this epoch. /// /// # Arguments @@ -867,26 +844,6 @@ impl StorageManager { Ok(()) } - /// Inserts information into the database about a gateway that might have been unfairly unrewarded this epoch. - /// - /// # Arguments - /// - /// * `gateway`: mixnode information to insert. - pub(super) async fn insert_possibly_unrewarded_gateway( - &self, - gateway: PossiblyUnrewardedGateway, - ) -> Result<(), sqlx::Error> { - sqlx::query!( - r#" - INSERT INTO possibly_unrewarded_gateway (identity, uptime, failed_gateway_reward_chunk_id) VALUES (?, ?, ?) - "#, - gateway.identity, - gateway.uptime, - gateway.chunk_id - ).execute(&self.connection_pool).await?; - Ok(()) - } - /// Obtains all statuses of active mixnodes from the specified time interval. /// /// # Arguments diff --git a/validator-api/src/storage/mod.rs b/validator-api/src/storage/mod.rs index 64cfac2487..e0ca1a5ffc 100644 --- a/validator-api/src/storage/mod.rs +++ b/validator-api/src/storage/mod.rs @@ -9,8 +9,8 @@ use crate::node_status_api::models::{ use crate::node_status_api::{ONE_DAY, ONE_HOUR}; use crate::storage::manager::StorageManager; use crate::storage::models::{ - EpochRewarding, FailedGatewayRewardChunk, FailedMixnodeRewardChunk, NodeStatus, - PossiblyUnrewardedGateway, PossiblyUnrewardedMixnode, RewardingReport, + EpochRewarding, FailedMixnodeRewardChunk, NodeStatus, PossiblyUnrewardedMixnode, + RewardingReport, }; use rocket::fairing::{self, AdHoc}; use rocket::{Build, Rocket}; @@ -648,22 +648,6 @@ impl NodeStatusStorage { .map_err(|_| NodeStatusApiError::InternalDatabaseError) } - /// Inserts new failed gateway reward chunk information into the database. - /// Returns id of the newly created entry. - /// - /// # Arguments - /// - /// * `failed_chunk`: chunk information to insert. - pub(crate) async fn insert_failed_gateway_reward_chunk( - &self, - failed_chunk: FailedGatewayRewardChunk, - ) -> Result { - self.manager - .insert_failed_gateway_reward_chunk(failed_chunk) - .await - .map_err(|_| NodeStatusApiError::InternalDatabaseError) - } - /// Inserts information into the database about a mixnode that might have been unfairly unrewarded this epoch. /// /// # Arguments @@ -678,19 +662,4 @@ impl NodeStatusStorage { .await .map_err(|_| NodeStatusApiError::InternalDatabaseError) } - - /// Inserts information into the database about a gateway that might have been unfairly unrewarded this epoch. - /// - /// # Arguments - /// - /// * `gateway`: mixnode information to insert. - pub(crate) async fn insert_possibly_unrewarded_gateway( - &self, - gateway: PossiblyUnrewardedGateway, - ) -> Result<(), NodeStatusApiError> { - self.manager - .insert_possibly_unrewarded_gateway(gateway) - .await - .map_err(|_| NodeStatusApiError::InternalDatabaseError) - } } diff --git a/validator-api/src/storage/models.rs b/validator-api/src/storage/models.rs index 8c878ca85d..1c5ffdf883 100644 --- a/validator-api/src/storage/models.rs +++ b/validator-api/src/storage/models.rs @@ -29,10 +29,8 @@ pub(crate) struct RewardingReport { pub(crate) epoch_rewarding_id: i64, pub(crate) eligible_mixnodes: i64, - pub(crate) eligible_gateways: i64, pub(crate) possibly_unrewarded_mixnodes: i64, - pub(crate) possibly_unrewarded_gateways: i64, } pub(crate) struct FailedMixnodeRewardChunk { @@ -47,16 +45,3 @@ pub(crate) struct PossiblyUnrewardedMixnode { pub(crate) identity: String, pub(crate) uptime: u8, } - -pub(crate) struct FailedGatewayRewardChunk { - // references particular epoch_rewarding (there can be multiple chunks in a rewarding epoch) - pub(crate) epoch_rewarding_id: i64, - pub(crate) error_message: String, -} - -pub(crate) struct PossiblyUnrewardedGateway { - // references particular FailedGatewayRewardChunk (there can be multiple nodes in a chunk) - pub(crate) chunk_id: i64, - pub(crate) identity: String, - pub(crate) uptime: u8, -}