Initial analysis

This commit is contained in:
Drazen Urch
2021-09-23 15:58:42 +02:00
parent 4a9cc5b757
commit 22a4b03ce6
17 changed files with 499 additions and 13 deletions
Generated
+105
View File
@@ -2628,6 +2628,29 @@ dependencies = [
"serde",
]
[[package]]
name = "indoc"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "47741a8bc60fb26eb8d6e0238bbb26d8575ff623fdc97b1a2c00c050b9684ed8"
dependencies = [
"indoc-impl",
"proc-macro-hack",
]
[[package]]
name = "indoc-impl"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce046d161f000fffde5f432a0d034d0341dc152643b2598ed5bfce44c4f3a8f0"
dependencies = [
"proc-macro-hack",
"proc-macro2",
"quote",
"syn",
"unindent",
]
[[package]]
name = "infer"
version = "0.4.0"
@@ -3790,6 +3813,25 @@ dependencies = [
"winapi",
]
[[package]]
name = "paste"
version = "0.1.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "45ca20c77d80be666aef2b45486da86238fabe33e38306bd3118fe4af33fa880"
dependencies = [
"paste-impl",
"proc-macro-hack",
]
[[package]]
name = "paste-impl"
version = "0.1.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d95a7db200b97ef370c8e6de0088252f7e0dfff7d047a28528e47456c0fc98b6"
dependencies = [
"proc-macro-hack",
]
[[package]]
name = "pbkdf2"
version = "0.8.0"
@@ -4230,6 +4272,54 @@ dependencies = [
"url",
]
[[package]]
name = "pyo3"
version = "0.14.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "35100f9347670a566a67aa623369293703322bb9db77d99d7df7313b575ae0c8"
dependencies = [
"cfg-if 1.0.0",
"indoc",
"libc",
"parking_lot",
"paste",
"pyo3-build-config",
"pyo3-macros",
"unindent",
]
[[package]]
name = "pyo3-build-config"
version = "0.14.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d12961738cacbd7f91b7c43bc25cfeeaa2698ad07a04b3be0aa88b950865738f"
dependencies = [
"once_cell",
]
[[package]]
name = "pyo3-macros"
version = "0.14.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc0bc5215d704824dfddddc03f93cb572e1155c68b6761c37005e1c288808ea8"
dependencies = [
"pyo3-macros-backend",
"quote",
"syn",
]
[[package]]
name = "pyo3-macros-backend"
version = "0.14.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "71623fc593224afaab918aa3afcaf86ed2f43d34f6afde7f3922608f253240df"
dependencies = [
"proc-macro2",
"pyo3-build-config",
"quote",
"syn",
]
[[package]]
name = "quick-error"
version = "1.2.3"
@@ -6289,6 +6379,15 @@ dependencies = [
"syn",
]
[[package]]
name = "tokenomics-py"
version = "0.1.0"
dependencies = [
"cosmwasm-std",
"mixnet-contract",
"pyo3",
]
[[package]]
name = "tokio"
version = "1.12.0"
@@ -6619,6 +6718,12 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e"
[[package]]
name = "unindent"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f14ee04d9415b52b3aeab06258a3f07093182b88ba0f9b8d203f211a7a7d41c7"
[[package]]
name = "untrusted"
version = "0.7.1"
+1
View File
@@ -50,6 +50,7 @@ members = [
"mixnode",
"service-providers/network-requester",
"validator-api",
"tokenomics-py"
]
default-members = [
@@ -182,6 +182,20 @@ impl<C> Client<C> {
Ok(self.nymd.get_state_params().await?)
}
pub async fn get_total_mix_stake(&self) -> Result<u128, ValidatorClientError>
where
C: CosmWasmClient + Sync,
{
Ok(self.nymd.get_total_mix_stake().await?.u128())
}
pub async fn get_total_gateway_stake(&self) -> Result<u128, ValidatorClientError>
where
C: CosmWasmClient + Sync,
{
Ok(self.nymd.get_total_gateway_stake().await?.u128())
}
// basically handles paging for us
pub async fn get_all_nymd_mixnodes(&self) -> Result<Vec<MixNodeBond>, ValidatorClientError>
where
@@ -12,6 +12,7 @@ use crate::nymd::wallet::DirectSecp256k1HdWallet;
use cosmrs::rpc::endpoint::broadcast;
use cosmrs::rpc::{Error as TendermintRpcError, HttpClientUrl};
use cosmwasm_std::Coin;
use cosmwasm_std::{Coin, Uint128};
use mixnet_contract::{
Addr, Delegation, ExecuteMsg, Gateway, GatewayOwnershipResponse, IdentityKey,
LayerDistribution, MixNode, MixOwnershipResponse, PagedAllDelegationsResponse,
@@ -212,6 +213,26 @@ impl<C> NymdClient<C> {
.await
}
pub async fn get_total_mix_stake(&self) -> Result<Uint128, NymdError>
where
C: CosmWasmClient + Sync,
{
let request = QueryMsg::GetTotalMixStake {};
self.client
.query_contract_smart(self.contract_address()?, &request)
.await
}
pub async fn get_total_gateway_stake(&self) -> Result<Uint128, NymdError>
where
C: CosmWasmClient + Sync,
{
let request = QueryMsg::GetTotalGatewayStake {};
self.client
.query_contract_smart(self.contract_address()?, &request)
.await
}
/// Checks whether there is a bonded mixnode associated with the provided client's address
pub async fn owns_mixnode(&self, address: &AccountId) -> Result<bool, NymdError>
where
+4
View File
@@ -59,6 +59,10 @@ impl GatewayBond {
pub fn gateway(&self) -> &Gateway {
&self.gateway
}
pub fn total_delegation(&self) -> Coin {
self.total_delegation.clone()
}
}
impl PartialOrd for GatewayBond {
+4
View File
@@ -79,6 +79,10 @@ impl MixNodeBond {
pub fn mix_node(&self) -> &MixNode {
&self.mix_node
}
pub fn total_delegation(&self) -> Coin {
self.total_delegation.clone()
}
}
impl PartialOrd for MixNodeBond {
+2
View File
@@ -107,6 +107,8 @@ pub enum QueryMsg {
address: Addr,
},
LayerDistribution {},
GetTotalMixStake {},
GetTotalGatewayStake {},
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
+5 -1
View File
@@ -207,13 +207,17 @@ pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> Result<QueryResponse, Cont
gateway_identity,
address,
)?),
QueryMsg::GetTotalMixStake {} => to_binary(&queries::query_total_mix_stake(deps)),
QueryMsg::GetTotalGatewayStake {} => to_binary(&queries::query_total_gt_stake(deps)),
};
Ok(query_res?)
}
#[entry_point]
pub fn migrate(_deps: DepsMut, _env: Env, _msg: MigrateMsg) -> Result<Response, ContractError> {
todo!("Calculate initial total mix and gateway stake after initial deployment");
#[allow(unreachable_code)]
Ok(Default::default())
}
+3
View File
@@ -89,4 +89,7 @@ pub enum ContractError {
identity: IdentityKey,
address: Addr,
},
#[error("Overflow error!")]
Overflow(#[from] cosmwasm_std::OverflowError),
}
+10 -2
View File
@@ -7,10 +7,10 @@ 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,
reverse_mix_delegations_read,
reverse_mix_delegations_read, total_gateway_stake_value, total_mix_stake_value,
};
use config::defaults::DENOM;
use cosmwasm_std::{coin, Addr, Deps, Order, StdResult};
use cosmwasm_std::{coin, Addr, Deps, Order, StdResult, Uint128};
use mixnet_contract::{
Delegation, GatewayBond, GatewayOwnershipResponse, IdentityKey, LayerDistribution, MixNodeBond,
MixOwnershipResponse, PagedAllDelegationsResponse, PagedGatewayDelegationsResponse,
@@ -93,6 +93,14 @@ pub(crate) fn query_layer_distribution(deps: Deps) -> LayerDistribution {
read_layer_distribution(deps.storage)
}
pub(crate) fn query_total_mix_stake(deps: Deps) -> Uint128 {
total_mix_stake_value(deps.storage)
}
pub(crate) fn query_total_gt_stake(deps: Deps) -> Uint128 {
total_gateway_stake_value(deps.storage)
}
/// Adds a 0 byte to terminate the `start_after` value given. This allows CosmWasm
/// to get the succeeding key as the start of the next page.
// S works for both `String` and `Addr` and that's what we wanted
+70 -1
View File
@@ -1,9 +1,9 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::queries;
use crate::state::State;
use crate::transactions::MINIMUM_BLOCK_AGE_FOR_REWARDING;
use crate::{error::ContractError, queries};
use cosmwasm_std::{Decimal, Order, StdResult, Storage, Uint128};
use cosmwasm_storage::{
bucket, bucket_read, singleton, singleton_read, Bucket, ReadonlyBucket, ReadonlySingleton,
@@ -24,6 +24,9 @@ use serde::Serialize;
// singletons
const CONFIG_KEY: &[u8] = b"config";
const LAYER_DISTRIBUTION_KEY: &[u8] = b"layers";
// Keeps total amount of stake towards mixnodes and gateways. Removing a bond removes all its delegations from the total, the reverse is true for adding a bond.
const TOTAL_MIX_STAKE_KEY: &[u8] = b"total_mn";
const TOTAL_GATEWAY_STAKE_KEY: &[u8] = b"total_gt";
// buckets
const PREFIX_MIXNODES: &[u8] = b"mn";
@@ -48,6 +51,72 @@ pub fn config_read(storage: &dyn Storage) -> ReadonlySingleton<State> {
singleton_read(storage, CONFIG_KEY)
}
fn total_mix_stake(storage: &dyn Storage) -> ReadonlySingleton<Uint128> {
singleton_read(storage, TOTAL_MIX_STAKE_KEY)
}
pub fn mut_total_mix_stake(storage: &mut dyn Storage) -> Singleton<Uint128> {
singleton(storage, TOTAL_MIX_STAKE_KEY)
}
fn total_gateway_stake(storage: &dyn Storage) -> ReadonlySingleton<Uint128> {
singleton_read(storage, TOTAL_GATEWAY_STAKE_KEY)
}
pub fn mut_total_gateway_stake(storage: &mut dyn Storage) -> Singleton<Uint128> {
singleton(storage, TOTAL_GATEWAY_STAKE_KEY)
}
pub fn total_mix_stake_value(storage: &dyn Storage) -> Uint128 {
match total_mix_stake(storage).load() {
Ok(value) => value,
Err(_e) => Uint128(0),
}
}
pub fn total_gateway_stake_value(storage: &dyn Storage) -> Uint128 {
match total_gateway_stake(storage).load() {
Ok(value) => value,
Err(_e) => Uint128(0),
}
}
pub fn incr_total_mix_stake(
amount: Uint128,
storage: &mut dyn Storage,
) -> Result<Uint128, ContractError> {
let stake = total_mix_stake_value(storage).checked_add(amount)?;
mut_total_mix_stake(storage).save(&stake)?;
Ok(stake)
}
pub fn decr_total_mix_stake(
amount: Uint128,
storage: &mut dyn Storage,
) -> Result<Uint128, ContractError> {
let stake = total_mix_stake_value(storage).checked_sub(amount)?;
mut_total_mix_stake(storage).save(&stake)?;
Ok(stake)
}
pub fn incr_total_gateway_stake(
amount: Uint128,
storage: &mut dyn Storage,
) -> Result<Uint128, ContractError> {
let stake = total_gateway_stake_value(storage).checked_add(amount)?;
mut_total_gateway_stake(storage).save(&stake)?;
Ok(stake)
}
pub fn decr_total_gateway_stake(
amount: Uint128,
storage: &mut dyn Storage,
) -> Result<Uint128, ContractError> {
let stake = total_gateway_stake_value(storage).checked_sub(amount)?;
mut_total_gateway_stake(storage).save(&stake)?;
Ok(stake)
}
pub(crate) fn read_state_params(storage: &dyn Storage) -> StateParams {
// note: In any other case, I wouldn't have attempted to unwrap this result, but in here
// if we fail to load the stored state we would already be in the undefined behaviour land,
+143 -4
View File
@@ -111,6 +111,8 @@ pub(crate) fn try_add_mixnode(
mixnodes(deps.storage).save(identity.as_bytes(), &bond)?;
mixnodes_owners(deps.storage).save(sender_bytes, identity)?;
increment_layer_count(deps.storage, bond.layer)?;
incr_total_mix_stake(bond.bond_amount().amount, deps.storage)?;
incr_total_mix_stake(bond.total_delegation().amount, deps.storage)?;
let attributes = vec![attr("overwritten", was_present)];
Ok(Response {
@@ -150,6 +152,9 @@ pub(crate) fn try_remove_mixnode(
// decrement layer count
decrement_layer_count(deps.storage, mixnode_bond.layer)?;
decr_total_mix_stake(mixnode_bond.bond_amount().amount, deps.storage)?;
decr_total_mix_stake(mixnode_bond.total_delegation().amount, deps.storage)?;
// log our actions
let attributes = vec![attr("action", "unbond"), attr("mixnode_bond", mixnode_bond)];
@@ -243,6 +248,9 @@ pub(crate) fn try_add_gateway(
gateways_owners(deps.storage).save(sender_bytes, identity)?;
increment_layer_count(deps.storage, Layer::Gateway)?;
incr_total_gateway_stake(bond.bond_amount().amount, deps.storage)?;
incr_total_gateway_stake(bond.total_delegation().amount, deps.storage)?;
let attributes = vec![attr("overwritten", was_present)];
Ok(Response {
submessages: Vec::new(),
@@ -281,6 +289,9 @@ pub(crate) fn try_remove_gateway(
// decrement layer count
decrement_layer_count(deps.storage, Layer::Gateway)?;
decr_total_gateway_stake(gateway_bond.bond_amount().amount, deps.storage)?;
decr_total_gateway_stake(gateway_bond.total_delegation().amount, deps.storage)?;
// log our actions
let attributes = vec![
attr("action", "unbond"),
@@ -561,8 +572,10 @@ pub(crate) fn try_delegate_to_mixnode(
}
};
let amount = info.funds[0].amount;
// update total_delegation of this node
current_bond.total_delegation.amount += info.funds[0].amount;
current_bond.total_delegation.amount += amount;
mixnodes_bucket.save(mix_identity.as_bytes(), &current_bond)?;
let mut delegation_bucket = mix_delegations(deps.storage, &mix_identity);
@@ -570,8 +583,8 @@ pub(crate) fn try_delegate_to_mixnode(
// 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,
Some(existing_delegation) => existing_delegation.amount + amount,
None => amount,
};
// the block height is reset, if it existed
let new_delegation = RawDelegationData::new(new_amount, env.block.height);
@@ -579,6 +592,8 @@ pub(crate) fn try_delegate_to_mixnode(
reverse_mix_delegations(deps.storage, &info.sender).save(mix_identity.as_bytes(), &())?;
incr_total_mix_stake(amount, deps.storage)?;
Ok(Response::default())
}
@@ -614,6 +629,8 @@ pub(crate) fn try_remove_delegation_from_mixnode(
.checked_sub(delegation.amount)
.unwrap();
mixnodes_bucket.save(mix_identity.as_bytes(), &existing_bond)?;
// We should only decr total if a node is bonded, node unbonding remove all delegations from the total
decr_total_mix_stake(delegation.amount, deps.storage)?;
}
Ok(Response {
@@ -669,6 +686,8 @@ pub(crate) fn try_delegate_to_gateway(
reverse_gateway_delegations(deps.storage, &info.sender)
.save(gateway_identity.as_bytes(), &())?;
incr_total_gateway_stake(info.funds[0].amount, deps.storage)?;
Ok(Response::default())
}
@@ -707,6 +726,8 @@ pub(crate) fn try_remove_delegation_from_gateway(
.checked_sub(delegation.amount)
.unwrap();
gateways_bucket.save(gateway_identity.as_bytes(), &existing_bond)?;
decr_total_gateway_stake(delegation.amount, deps.storage)?;
}
Ok(Response {
@@ -3494,7 +3515,7 @@ pub mod tests {
}
#[test]
fn delegation_is_not_removed_if_node_unbonded() {
fn delegation_is_not_removed_if_gateway_unbonded() {
let mut deps = helpers::init_contract();
let gateway_owner = "bob";
@@ -4001,4 +4022,122 @@ pub mod tests {
assert_eq!(bob_node.mix_node.identity_key, "bob");
assert_eq!(bob_node.layer, Layer::Two);
}
#[test]
fn mix_stake_accounting() {
let mut deps = helpers::init_contract();
let mut test_bond = INITIAL_MIXNODE_BOND;
try_add_mixnode(
deps.as_mut(),
mock_env(),
mock_info("alice", &good_mixnode_bond()),
MixNode {
identity_key: "alice".to_string(),
..helpers::mix_node_fixture()
},
)
.unwrap();
assert_eq!(total_mix_stake_value(&deps.storage), test_bond);
let delegation = coin(100, DENOM);
try_delegate_to_mixnode(
deps.as_mut(),
mock_env(),
mock_info("bob", &vec![delegation.clone()]),
"alice".to_string(),
)
.unwrap();
test_bond += Uint128(100);
assert_eq!(total_mix_stake_value(&deps.storage), test_bond);
try_remove_mixnode(deps.as_mut(), mock_info("alice", &[])).unwrap();
test_bond = Uint128(0);
assert_eq!(total_mix_stake_value(&deps.storage), test_bond);
try_add_mixnode(
deps.as_mut(),
mock_env(),
mock_info("alice", &good_mixnode_bond()),
MixNode {
identity_key: "alice".to_string(),
..helpers::mix_node_fixture()
},
)
.unwrap();
test_bond = Uint128(100) + INITIAL_MIXNODE_BOND;
assert_eq!(total_mix_stake_value(&deps.storage), test_bond);
try_remove_delegation_from_mixnode(
deps.as_mut(),
mock_info("bob", &[]),
"alice".to_string(),
)
.unwrap();
test_bond = test_bond.checked_sub(Uint128(100)).unwrap();
assert_eq!(total_mix_stake_value(&deps.storage), test_bond);
}
#[test]
fn gateway_stake_accounting() {
let mut deps = helpers::init_contract();
let mut test_bond = INITIAL_GATEWAY_BOND;
try_add_gateway(
deps.as_mut(),
mock_env(),
mock_info("alice", &good_gateway_bond()),
Gateway {
identity_key: "alice".to_string(),
..helpers::gateway_fixture()
},
)
.unwrap();
assert_eq!(total_gateway_stake_value(&deps.storage), test_bond);
let delegation = coin(100, DENOM);
try_delegate_to_gateway(
deps.as_mut(),
mock_env(),
mock_info("bob", &vec![delegation.clone()]),
"alice".to_string(),
)
.unwrap();
test_bond += Uint128(100);
assert_eq!(total_gateway_stake_value(&deps.storage), test_bond);
try_remove_gateway(deps.as_mut(), mock_info("alice", &[])).unwrap();
test_bond = Uint128(0);
assert_eq!(total_gateway_stake_value(&deps.storage), test_bond);
try_add_gateway(
deps.as_mut(),
mock_env(),
mock_info("alice", &good_gateway_bond()),
Gateway {
identity_key: "alice".to_string(),
..helpers::gateway_fixture()
},
)
.unwrap();
test_bond = Uint128(100) + INITIAL_GATEWAY_BOND;
assert_eq!(total_gateway_stake_value(&deps.storage), test_bond);
try_remove_delegation_from_gateway(
deps.as_mut(),
mock_info("bob", &[]),
"alice".to_string(),
)
.unwrap();
test_bond = test_bond.checked_sub(Uint128(100)).unwrap();
assert_eq!(total_gateway_stake_value(&deps.storage), test_bond);
}
}
+20
View File
@@ -0,0 +1,20 @@
[package]
name = "tokenomics-py"
version = "0.1.0"
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[lib]
name = "tokenomics_py"
crate-type = ["cdylib"]
[dependencies]
mixnet-contract = {path = "../common/mixnet-contract"}
cosmwasm-std = { git = "https://github.com/jstuczyn/cosmwasm", branch="0.14.1-updatedk256" }
[dependencies.pyo3]
version = "0.14.5"
features = ["extension-module"]
+49
View File
@@ -0,0 +1,49 @@
use cosmwasm_std::Uint128;
use mixnet_contract::MixNodeBond;
use pyo3::prelude::*;
const ACTIVE_MIX_SET_SIZE: u32 = 1000;
#[pymodule]
fn tokenomics_py(_py: Python, m: &PyModule) -> PyResult<()> {
m.add_function(wrap_pyfunction!(compute_mix_rewards_py, m)?)?;
Ok(())
}
// assign_rewards_to_nodes, Econ_results:344
#[pyfunction]
fn compute_mix_rewards_py(
pledged: f64,
delegated: f64,
total_stake: f64, // total stake delegated across the network, ideally persisted in the blockchain
performance: f64, // uptime ?
income_global_mix: f64, // inflation pool
omega_k: f64, // work_share * number of noes, where workshare is considered uniform 1/k, so it follows this is k in the uniform case
alpha: f64, // sybil resistance param - externally defined constant
k: f64, // number of desired mixnodes - externally defined constant
) -> f64 {
// set_lambda_sigma_mixnet, Network_econ:308
let lambda = (pledged / total_stake).min(1. / k);
let sigma = ((pledged + delegated) / total_stake).min(1. / k);
performance * income_global_mix * (sigma * omega_k + alpha * lambda) / (1. + alpha)
}
fn compute_mix_rewards(mix: &MixNodeBond) {
let k = ACTIVE_MIX_SET_SIZE as f64;
let one_over_k = 1. / k;
let one_over_k_uint = (one_over_k * 1_000_000.) as u128;
// Assume uniform node work distribution for simplicity
let work_share = one_over_k;
let omega_k = work_share * k;
// TODO: Use Coin struct from the Tauri wallet, this must be in the Minor denom it will be much easier then
}
// TODO:
// Compute total stake across the entire network, open question is how to handle orphaned delegations
// Compute performance as uptime, uptime can be obtained from the validator API, might be useful to introduce some sugar functions. Validator API is also not available from the contract most likely
// Compute workshare, as either 1/k or node uptime / total uptime, probably best to assume 1/k for now
// k is the active set size
// Where should the inflation pool size be set
+31 -5
View File
@@ -37,6 +37,9 @@ struct ValidatorCacheInner {
current_mixnode_active_set_size: AtomicUsize,
current_gateway_active_set_size: AtomicUsize,
total_mix_stake: RwLock<Cache<u128>>,
total_gateway_stake: RwLock<Cache<u128>>,
}
#[derive(Default, Serialize, Clone)]
@@ -76,21 +79,30 @@ impl<C> ValidatorCacheRefresher<C> {
where
C: CosmWasmClient + Sync,
{
let (mixnodes, gateways) = tokio::try_join!(
let (mixnodes, gateways, total_mix_stake, total_gt_state) = tokio::try_join!(
self.nymd_client.get_mixnodes(),
self.nymd_client.get_gateways()
self.nymd_client.get_gateways(),
self.nymd_client.get_total_mix_stake(),
self.nymd_client.get_total_gateway_stake()
)?;
let state_params = self.nymd_client.get_state_params().await?;
info!(
"Updating validator cache. There are {} mixnodes and {} gateways",
"Updating validator cache. There are {} mixnodes and {} gateways, total_mix_stake is {}",
mixnodes.len(),
gateways.len()
gateways.len(),
total_mix_stake
);
self.cache
.update_cache(mixnodes, gateways, state_params)
.update_cache(
mixnodes,
gateways,
total_mix_stake,
total_gt_state,
state_params,
)
.await;
Ok(())
@@ -177,6 +189,8 @@ impl ValidatorCache {
&self,
mut mixnodes: Vec<MixNodeBond>,
mut gateways: Vec<GatewayBond>,
total_mix_stake: u128,
total_gt_stake: u128,
state: StateParams,
) {
// if our data is valid, it means the active sets are available,
@@ -218,6 +232,16 @@ impl ValidatorCache {
self.inner.mixnodes.write().await.set(mixnodes);
self.inner.gateways.write().await.set(gateways);
self.inner
.total_mix_stake
.write()
.await
.set(total_mix_stake);
self.inner
.total_gateway_stake
.write()
.await
.set(total_gt_stake);
}
pub async fn mixnodes(&self) -> Cache<Vec<MixNodeBond>> {
@@ -303,6 +327,8 @@ impl ValidatorCacheInner {
active_gateways_available: AtomicBool::new(false),
current_mixnode_active_set_size: Default::default(),
current_gateway_active_set_size: Default::default(),
total_mix_stake: Default::default(),
total_gateway_stake: Default::default(),
}
}
}
+14
View File
@@ -94,6 +94,20 @@ impl<C> Client<C> {
Ok(time)
}
pub(crate) async fn get_total_mix_stake(&self) -> Result<u128, ValidatorClientError>
where
C: CosmWasmClient + Sync,
{
Ok(self.0.read().await.get_total_mix_stake().await?)
}
pub(crate) async fn get_total_gateway_stake(&self) -> Result<u128, ValidatorClientError>
where
C: CosmWasmClient + Sync,
{
Ok(self.0.read().await.get_total_gateway_stake().await?)
}
pub(crate) async fn get_mixnodes(&self) -> Result<Vec<MixNodeBond>, ValidatorClientError>
where
C: CosmWasmClient + Sync,
+3
View File
@@ -54,6 +54,8 @@ pub(crate) struct MixnodeToReward {
/// Total number of individual addresses that have delegated to this particular node
pub(crate) total_delegations: usize,
/// Node absolute uptime over total active set uptime
pub(crate) performance: Option<f64>
}
#[derive(Debug, Clone)]
@@ -285,6 +287,7 @@ impl Rewarder {
uptime: self
.calculate_absolute_uptime(mix.last_day_ipv4, mix.last_day_ipv6),
total_delegations,
performance: None
})
})
.filter(|node| node.uptime.u8() > 0)