Skip to content

Commit

Permalink
latest state (to organize later)
Browse files Browse the repository at this point in the history
  • Loading branch information
brentstone committed Oct 28, 2022
1 parent e3e97e8 commit 35c617d
Show file tree
Hide file tree
Showing 17 changed files with 210 additions and 190 deletions.
1 change: 0 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

51 changes: 26 additions & 25 deletions apps/src/lib/client/rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,10 @@ use namada::ledger::governance::parameters::GovParams;
use namada::ledger::governance::storage as gov_storage;
use namada::ledger::governance::utils::Votes;
use namada::ledger::parameters::{storage as param_storage, EpochDuration};
use namada::ledger::pos::types::{
Epoch as PosEpoch, WeightedValidator,
};
use namada::ledger::pos::types::{Epoch as PosEpoch, WeightedValidator};
use namada::ledger::pos::{
self, is_validator_slashes_key, BondId, Bonds, PosParams, Slash, Unbonds, into_tm_voting_power,
self, into_tm_voting_power, is_validator_slashes_key, BondId, Bonds,
PosParams, Slash, Unbonds,
};
use namada::types::address::Address;
use namada::types::governance::{
Expand Down Expand Up @@ -938,17 +937,18 @@ pub async fn query_voting_power(ctx: Context, args: args::QueryVotingPower) {
Some(validator) => {
let validator = ctx.get(&validator);
// Find voting power for the given validator
let validator_deltas_key =
pos::validator_deltas_key(&validator);
let validator_deltas = query_storage_value::<
pos::ValidatorDeltas,
>(&client, &validator_deltas_key)
let validator_deltas_key = pos::validator_deltas_key(&validator);
let validator_deltas = query_storage_value::<pos::ValidatorDeltas>(
&client,
&validator_deltas_key,
)
.await;
match validator_deltas.and_then(|data| data.get(epoch)) {
Some(val_stake) => {
let bonded_stake: u64 = val_stake.try_into().expect(
"The sum of the bonded stake deltas shouldn't be negative",
);
"The sum of the bonded stake deltas shouldn't be \
negative",
);
let weighted = WeightedValidator {
address: validator.clone(),
bonded_stake,
Expand Down Expand Up @@ -1001,22 +1001,24 @@ pub async fn query_voting_power(ctx: Context, args: args::QueryVotingPower) {
}
}
let total_deltas_key = pos::total_deltas_key();
let total_deltas = query_storage_value::<pos::TotalDeltas>(
&client,
&total_deltas_key,
)
.await
.expect("Total bonded stake should always be set");
let total_deltas =
query_storage_value::<pos::TotalDeltas>(&client, &total_deltas_key)
.await
.expect("Total bonded stake should always be set");
let total_bonded_stake = total_deltas
.get(epoch)
.expect("Total bonded stake should be always set in the current epoch");
let pos_params_key = pos::params_key();
let pos_params = query_storage_value::<pos::PosParams>(&client, &pos_params_key)
.await
.expect("PoS parameters should always exist in storage");
let total_bonded_stake: u64 = total_bonded_stake.try_into().expect("total_bonded_stake should be a positive value");
let total_voting_power = into_tm_voting_power(pos_params.tm_votes_per_token, total_bonded_stake);

let pos_params =
query_storage_value::<pos::PosParams>(&client, &pos_params_key)
.await
.expect("PoS parameters should always exist in storage");
let total_bonded_stake: u64 = total_bonded_stake
.try_into()
.expect("total_bonded_stake should be a positive value");
let total_voting_power =
into_tm_voting_power(pos_params.votes_per_token, total_bonded_stake);

println!("Total voting power: {}", total_voting_power);
}

Expand Down Expand Up @@ -1963,8 +1965,7 @@ async fn get_validator_stake(
.expect("Total deltas should be defined");
let validator_stake = validator_deltas.get(epoch);

VotePower::try_from(validator_stake.unwrap_or_default())
.unwrap_or_default()
VotePower::try_from(validator_stake.unwrap_or_default()).unwrap_or_default()
}

pub async fn get_delegators_delegation(
Expand Down
6 changes: 3 additions & 3 deletions apps/src/lib/config/genesis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ pub mod genesis_config {
use namada::types::time::Rfc3339String;
use namada::types::{storage, token};
use rust_decimal::Decimal;
use rust_decimal_macros::dec;
use serde::{Deserialize, Serialize};
use thiserror::Error;

Expand Down Expand Up @@ -547,9 +548,8 @@ pub mod genesis_config {
max_validator_slots: config.pos_params.max_validator_slots,
pipeline_len: config.pos_params.pipeline_len,
unbonding_len: config.pos_params.unbonding_len,
votes_per_token: BasisPoints::new(
config.pos_params.votes_per_token,
),
votes_per_token: Decimal::from(config.pos_params.votes_per_token)
/ dec!(10_000),
block_proposer_reward: config.pos_params.block_proposer_reward,
block_vote_reward: config.pos_params.block_vote_reward,
duplicate_vote_slash_rate: BasisPoints::new(
Expand Down
5 changes: 4 additions & 1 deletion apps/src/lib/node/ledger/shell/init_chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,10 @@ where
sum: Some(key_to_tendermint(&consensus_key).unwrap()),
};
abci_validator.pub_key = Some(pub_key);
abci_validator.power = into_tm_voting_power(genesis.pos_params.tm_votes_per_token, validator.pos_data.tokens);
abci_validator.power = into_tm_voting_power(
genesis.pos_params.votes_per_token,
validator.pos_data.tokens,
);
response.validators.push(abci_validator);
}
Ok(response)
Expand Down
29 changes: 13 additions & 16 deletions proof_of_stake/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,9 @@ use rust_decimal::Decimal;
use thiserror::Error;
use types::{
ActiveValidator, Bonds, CommissionRates, Epoch, GenesisValidator, Slash,
SlashType, Slashes, TotalVotingPowers, Unbond, Unbonds,
ValidatorConsensusKeys, ValidatorSet, ValidatorSetUpdate, ValidatorSets,
ValidatorState, ValidatorStates, ValidatorDeltas,
TotalDeltas
SlashType, Slashes, TotalDeltas, Unbond, Unbonds, ValidatorConsensusKeys,
ValidatorDeltas, ValidatorSet, ValidatorSetUpdate, ValidatorSets,
ValidatorState, ValidatorStates,
};

use crate::btree_set::BTreeSetShims;
Expand Down Expand Up @@ -158,7 +157,9 @@ pub trait PosReadOnly {
&self,
) -> Result<ValidatorSets<Self::Address>, Self::Error>;
/// Read PoS total deltas for all validators (active and inactive)
fn read_total_deltas(&self) -> Result<TotalDeltas<Self::TokenChange>, Self::Error>;
fn read_total_deltas(
&self,
) -> Result<TotalDeltas<Self::TokenChange>, Self::Error>;
}

/// PoS system trait to be implemented in integration that can read and write
Expand Down Expand Up @@ -244,7 +245,6 @@ pub trait PosActions: PosReadOnly {
&mut self,
value: TotalDeltas<Self::TokenChange>,
) -> Result<(), Self::Error>;
) -> Result<(), Self::Error>;
/// Delete an emptied PoS bond (validator self-bond or a delegation).
fn delete_bond(
&mut self,
Expand Down Expand Up @@ -285,8 +285,7 @@ pub trait PosActions: PosReadOnly {
let BecomeValidatorData {
consensus_key,
state,
total_deltas,
voting_power,
deltas,
commission_rate,
max_commission_rate_change,
} = become_validator(
Expand Down Expand Up @@ -350,8 +349,7 @@ pub trait PosActions: PosReadOnly {
validator: validator.clone(),
};
let bond = self.read_bond(&bond_id)?;
let validator_deltas =
self.read_validator_deltas(validator)?;
let validator_deltas = self.read_validator_deltas(validator)?;
let mut total_deltas = self.read_total_deltas()?;
let mut validator_set = self.read_validator_set()?;

Expand Down Expand Up @@ -406,9 +404,8 @@ pub trait PosActions: PosReadOnly {
None => Err(UnbondError::NoBondFound)?,
};
let unbond = self.read_unbond(&bond_id)?;
let mut validator_deltas = self
.read_validator_deltas(validator)?
.ok_or_else(|| {
let mut validator_deltas =
self.read_validator_deltas(validator)?.ok_or_else(|| {
UnbondError::ValidatorHasNoBonds(validator.clone())
})?;
let slashes = self.read_validator_slashes(validator)?;
Expand Down Expand Up @@ -1249,7 +1246,8 @@ where
} in validators.clone()
{
total_bonded_balance += *tokens;
// is some extra error handling needed here for casting the delta as i64? (TokenChange)
// is some extra error handling needed here for casting the delta as
// i64? (TokenChange)
let delta = TokenChange::from(*tokens);
total_bonded_delta = total_bonded_delta + delta;
active.insert(WeightedValidator {
Expand Down Expand Up @@ -1491,7 +1489,7 @@ where
BecomeValidatorData {
consensus_key,
state,
total_deltas,
deltas,
commission_rate,
max_commission_rate_change,
}
Expand Down Expand Up @@ -1656,7 +1654,6 @@ where

total_deltas.add_at_offset(delta, current_epoch, update_offset, params);


Ok(BondData {
bond,
validator_deltas,
Expand Down
23 changes: 14 additions & 9 deletions proof_of_stake/src/parameters.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
//! Proof-of-Stake system parameters
use borsh::{BorshDeserialize, BorshSerialize};
use rust_decimal::prelude::ToPrimitive;
use rust_decimal::Decimal;
use rust_decimal_macros::dec;
use thiserror::Error;

use crate::types::BasisPoints;
Expand All @@ -20,7 +23,7 @@ pub struct PosParams {
pub unbonding_len: u64,
/// Used in validators' voting power calculation. Given in basis points
/// (voting power per ten thousand tokens).
pub votes_per_token: BasisPoints,
pub votes_per_token: Decimal,
/// Amount of tokens rewarded to a validator for proposing a block
pub block_proposer_reward: u64,
/// Amount of tokens rewarded to each validator that voted on a block
Expand All @@ -41,7 +44,7 @@ impl Default for PosParams {
pipeline_len: 2,
unbonding_len: 6,
// 1 voting power per 1000 tokens
votes_per_token: BasisPoints::new(10),
votes_per_token: dec!(0.001),
block_proposer_reward: 100,
block_vote_reward: 1,
// slash 5%
Expand All @@ -61,7 +64,7 @@ pub enum ValidationError {
)]
TotalVotingPowerTooLarge(u64),
#[error("Votes per token cannot be greater than 1, got {0}")]
VotesPerTokenGreaterThanOne(BasisPoints),
VotesPerTokenGreaterThanOne(Decimal),
#[error("Pipeline length must be >= 2, got {0}")]
PipelineLenTooShort(u64),
#[error(
Expand Down Expand Up @@ -101,23 +104,23 @@ impl PosParams {

// Check maximum total voting power cannot get larger than what
// Tendermint allows
let max_total_voting_power = self.max_validator_slots
* (self.votes_per_token * TOKEN_MAX_AMOUNT);
let max_total_voting_power = Decimal::from(self.max_validator_slots)
* (self.votes_per_token * Decimal::from(TOKEN_MAX_AMOUNT));
match i64::try_from(max_total_voting_power) {
Ok(max_total_voting_power_i64) => {
if max_total_voting_power_i64 > MAX_TOTAL_VOTING_POWER {
errors.push(ValidationError::TotalVotingPowerTooLarge(
max_total_voting_power,
max_total_voting_power.to_u64().unwrap(),
))
}
}
Err(_) => errors.push(ValidationError::TotalVotingPowerTooLarge(
max_total_voting_power,
max_total_voting_power.to_u64().unwrap(),
)),
}

// Check that there is no more than 1 vote per token
if self.votes_per_token > BasisPoints::new(10_000) {
if self.votes_per_token > Decimal::ONE {
errors.push(ValidationError::VotesPerTokenGreaterThanOne(
self.votes_per_token,
))
Expand Down Expand Up @@ -153,6 +156,8 @@ mod tests {
#[cfg(any(test, feature = "testing"))]
pub mod testing {
use proptest::prelude::*;
use rust_decimal::Decimal;
use rust_decimal_macros::dec;

use super::*;

Expand All @@ -170,7 +175,7 @@ pub mod testing {
max_validator_slots,
pipeline_len,
unbonding_len,
votes_per_token: BasisPoints::new(votes_per_token),
votes_per_token: Decimal::from(votes_per_token) / dec!(10_000),
// The rest of the parameters that are not being used in the PoS
// VP are constant for now
..Default::default()
Expand Down
34 changes: 25 additions & 9 deletions proof_of_stake/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,10 @@ use std::collections::{BTreeSet, HashMap};
use std::convert::TryFrom;
use std::fmt::Display;
use std::hash::Hash;
use std::num::TryFromIntError;
use std::ops::{Add, AddAssign, Mul, Sub, SubAssign};
use std::ops::{Add, AddAssign, Mul, Sub};

use borsh::{BorshDeserialize, BorshSchema, BorshSerialize};
use rust_decimal::Decimal;
use rust_decimal::prelude::{Decimal, ToPrimitive};

use crate::epoched::{
Epoched, EpochedDelta, OffsetPipelineLen, OffsetUnbondingLen,
Expand All @@ -35,7 +34,8 @@ pub type Unbonds<TokenAmount> =
pub type ValidatorSets<Address> =
Epoched<ValidatorSet<Address>, OffsetUnbondingLen>;
/// Epoched total deltas.
pub type TotalDeltas<TokenChange> = EpochedDelta<TokenChange, OffsetUnbondingLen>;
pub type TotalDeltas<TokenChange> =
EpochedDelta<TokenChange, OffsetUnbondingLen>;
/// Epoched validator commission rate
pub type CommissionRates = Epoched<Decimal, OffsetPipelineLen>;

Expand Down Expand Up @@ -329,9 +329,6 @@ pub trait PublicKeyTmRawHash {
fn tm_raw_hash(&self) -> String;
}




impl Epoch {
/// Iterate a range of consecutive epochs starting from `self` of a given
/// length. Work-around for `Step` implementation pending on stabilization of <https://github.com/rust-lang/rust/issues/42168>.
Expand Down Expand Up @@ -580,11 +577,30 @@ impl Mul<i128> for BasisPoints {
}
}

/// Calculate voting power in the tendermint context (which is stored as i64) from the number of tokens
pub fn into_tm_voting_power(votes_per_token: Decimal, tokens: impl Into<u64>) -> i64 {
/// Calculate voting power in the tendermint context (which is stored as i64)
/// from the number of tokens
pub fn into_tm_voting_power(
votes_per_token: Decimal,
tokens: impl Into<u64>,
) -> i64 {
let prod = decimal_mult_u64(votes_per_token, tokens.into());
i64::try_from(prod).expect("Invalid voting power")
}
/// Multiply a value of type Decimal with one of type u64 and then return the
/// truncated u64
pub fn decimal_mult_u64(dec: Decimal, int: u64) -> u64 {
let prod = dec * Decimal::from(int);
// truncate the number to the floor
prod.to_u64().expect("Product is out of bounds")
}

/// Multiply a value of type Decimal with one of type i128 and then return the
/// truncated i128
pub fn decimal_mult_i128(dec: Decimal, int: i128) -> i128 {
let prod = dec * Decimal::from(int);
// truncate the number to the floor
prod.to_i128().expect("Product is out of bounds")
}

#[cfg(test)]
pub mod tests {
Expand Down
Loading

0 comments on commit 35c617d

Please sign in to comment.