From f5ec90c5047ff836094ed37eb978dfdd7c980877 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Zemanovi=C4=8D?= Date: Mon, 21 Nov 2022 16:21:50 +0100 Subject: [PATCH] pos: replace generic types with concrete types from core --- apps/src/lib/client/rpc.rs | 13 +- proof_of_stake/src/epoched.rs | 2 +- proof_of_stake/src/lib.rs | 1052 +++++++---------------------- proof_of_stake/src/storage.rs | 155 ++--- proof_of_stake/src/types.rs | 154 ++--- proof_of_stake/src/validation.rs | 654 +++++------------- shared/src/ledger/pos/mod.rs | 40 +- shared/src/ledger/pos/vp.rs | 6 +- tests/src/native_vp/pos.rs | 6 +- tx_prelude/src/proof_of_stake.rs | 58 +- wasm/wasm_source/src/tx_bond.rs | 21 +- wasm/wasm_source/src/tx_unbond.rs | 18 +- 12 files changed, 571 insertions(+), 1608 deletions(-) diff --git a/apps/src/lib/client/rpc.rs b/apps/src/lib/client/rpc.rs index e95e50292c..2b499a4cb8 100644 --- a/apps/src/lib/client/rpc.rs +++ b/apps/src/lib/client/rpc.rs @@ -27,9 +27,7 @@ use namada::ledger::governance::parameters::GovParams; use namada::ledger::governance::storage as gov_storage; use namada::ledger::native_vp::governance::utils::Votes; use namada::ledger::parameters::{storage as param_storage, EpochDuration}; -use namada::ledger::pos::types::{ - decimal_mult_u64, Epoch as PosEpoch, WeightedValidator, -}; +use namada::ledger::pos::types::{decimal_mult_u64, WeightedValidator}; use namada::ledger::pos::{ self, is_validator_slashes_key, BondId, Bonds, PosParams, Slash, Unbonds, }; @@ -2012,8 +2010,8 @@ pub async fn known_address( fn apply_slashes( slashes: &[Slash], mut delta: token::Amount, - epoch_start: PosEpoch, - withdraw_epoch: Option, + epoch_start: Epoch, + withdraw_epoch: Option, mut w: Option<&mut std::io::StdoutLock>, ) -> token::Amount { let mut slashed = token::Amount::default(); @@ -2638,11 +2636,8 @@ pub async fn get_proposal_offline_votes( .await .unwrap_or_default(); let mut delegated_amount: token::Amount = 0.into(); - let epoch = namada::ledger::pos::types::Epoch::from( - proposal.tally_epoch.0, - ); let bond = epoched_bonds - .get(epoch) + .get(proposal.tally_epoch) .expect("Delegation bond should be defined."); let mut to_deduct = bond.neg_deltas; for (start_epoch, &(mut delta)) in diff --git a/proof_of_stake/src/epoched.rs b/proof_of_stake/src/epoched.rs index cc2f24f1a8..03cf40228e 100644 --- a/proof_of_stake/src/epoched.rs +++ b/proof_of_stake/src/epoched.rs @@ -5,8 +5,8 @@ use core::marker::PhantomData; use core::{cmp, fmt, ops}; use borsh::{BorshDeserialize, BorshSchema, BorshSerialize}; +use namada_core::types::storage::Epoch; -use crate::types::Epoch; use crate::PosParams; /// Data that may have values set for future epochs, up to an epoch at offset as diff --git a/proof_of_stake/src/lib.rs b/proof_of_stake/src/lib.rs index 6081ceba76..0d16045b83 100644 --- a/proof_of_stake/src/lib.rs +++ b/proof_of_stake/src/lib.rs @@ -22,22 +22,21 @@ pub mod validation; use core::fmt::Debug; use std::collections::{BTreeSet, HashMap, HashSet}; use std::convert::TryFrom; -use std::fmt::Display; -use std::hash::Hash; use std::num::TryFromIntError; -use std::ops::{Add, AddAssign, Neg, Sub, SubAssign}; -use borsh::{BorshDeserialize, BorshSchema, BorshSerialize}; use epoched::{ DynEpochOffset, EpochOffset, Epoched, EpochedDelta, OffsetPipelineLen, }; use namada_core::ledger::storage_api; use namada_core::types::address::{self, Address, InternalAddress}; +use namada_core::types::key::common; +use namada_core::types::storage::Epoch; +use namada_core::types::token; pub use parameters::PosParams; use rust_decimal::Decimal; use thiserror::Error; use types::{ - ActiveValidator, Bonds, CommissionRates, Epoch, GenesisValidator, Slash, + ActiveValidator, Bonds, CommissionRates, GenesisValidator, Slash, SlashType, Slashes, TotalDeltas, Unbond, Unbonds, ValidatorConsensusKeys, ValidatorDeltas, ValidatorSet, ValidatorSetUpdate, ValidatorSets, ValidatorState, ValidatorStates, @@ -62,126 +61,69 @@ pub fn staking_token_address() -> Address { /// Read-only part of the PoS system pub trait PosReadOnly { - /// Address type - type Address: Display - + Debug - + Clone - + PartialEq - + Eq - + PartialOrd - + Ord - + Hash - + BorshDeserialize - + BorshSerialize - + BorshSchema; - /// Token amount type - type TokenAmount: Display - + Debug - + Default - + Clone - + Copy - + Add - + AddAssign - + Sub - + PartialOrd - + Into - + From - + Into - + SubAssign - + BorshDeserialize - + BorshSerialize - + BorshSchema; - /// Token change type - type TokenChange: Display - + Debug - + Default - + Clone - + Copy - + Add - + Sub - + From - + Into - + Neg - + BorshDeserialize - + BorshSerialize - + BorshSchema; - /// Cryptographic public key type - type PublicKey: Debug - + Clone - + BorshDeserialize - + BorshSerialize - + BorshSchema; - - /// Underlying read (and write in [`PosActions`]) interface errors - type Error; - /// Address of the PoS account - const POS_ADDRESS: Self::Address; + const POS_ADDRESS: Address; /// Address of the staking token - fn staking_token_address(&self) -> Self::Address; + fn staking_token_address(&self) -> Address; /// Read PoS parameters. - fn read_pos_params(&self) -> Result; + fn read_pos_params(&self) -> Result; /// Read PoS validator's consensus key (used for signing block votes). fn read_validator_consensus_key( &self, - key: &Self::Address, - ) -> Result>, Self::Error>; + key: &Address, + ) -> Result, storage_api::Error>; /// Read PoS validator's state. fn read_validator_state( &self, - key: &Self::Address, - ) -> Result, Self::Error>; + key: &Address, + ) -> Result, storage_api::Error>; /// Read PoS validator's total deltas of their bonds (validator self-bonds /// and delegations). fn read_validator_deltas( &self, - key: &Self::Address, - ) -> Result>, Self::Error>; + key: &Address, + ) -> Result, storage_api::Error>; /// Read PoS slashes applied to a validator. fn read_validator_slashes( &self, - key: &Self::Address, - ) -> Result, Self::Error>; + key: &Address, + ) -> Result, storage_api::Error>; /// Read PoS validator's commission rate for delegation rewards fn read_validator_commission_rate( &self, - key: &Self::Address, - ) -> Result, Self::Error>; + key: &Address, + ) -> Result, storage_api::Error>; /// Read PoS validator's maximum change in the commission rate for /// delegation rewards fn read_validator_max_commission_rate_change( &self, - key: &Self::Address, - ) -> Result, Self::Error>; + key: &Address, + ) -> Result, storage_api::Error>; /// Read PoS bond (validator self-bond or a delegation). fn read_bond( &self, - key: &BondId, - ) -> Result>, Self::Error>; + key: &BondId, + ) -> Result, storage_api::Error>; /// Read PoS unbond (unbonded tokens from validator self-bond or a /// delegation). fn read_unbond( &self, - key: &BondId, - ) -> Result>, Self::Error>; + key: &BondId, + ) -> Result, storage_api::Error>; /// Read PoS validator set (active and inactive). - fn read_validator_set( - &self, - ) -> Result, Self::Error>; + fn read_validator_set(&self) -> Result; /// Read PoS total deltas for all validators (active and inactive) - fn read_total_deltas( - &self, - ) -> Result, Self::Error>; + fn read_total_deltas(&self) -> Result; /// Check if the given address is a validator by checking that it has some /// state. fn is_validator( &self, - address: &Self::Address, - ) -> Result { + address: &Address, + ) -> Result { let state = self.read_validator_state(address)?; Ok(state.is_some()) } @@ -189,9 +131,9 @@ pub trait PosReadOnly { /// Get the total bond amount for the given bond ID at the given epoch. fn bond_amount( &self, - bond_id: &BondId, - epoch: impl Into, - ) -> Result { + bond_id: &BondId, + epoch: Epoch, + ) -> Result { // TODO new slash logic let slashes = self.read_validator_slashes(&bond_id.validator)?; // TODO apply rewards, if any @@ -214,7 +156,7 @@ pub trait PosReadOnly { } } let neg_deltas: u64 = bond.neg_deltas.into(); - Self::TokenAmount::from(total - neg_deltas) + token::Amount::from(total - neg_deltas) }) }) .unwrap_or_default()) @@ -224,8 +166,8 @@ pub trait PosReadOnly { /// state, e.g. active, inactive or jailed. fn validator_addresses( &self, - epoch: impl Into, - ) -> Result, Self::Error> { + epoch: Epoch, + ) -> Result, storage_api::Error> { let validator_sets = self.read_validator_set()?; let validator_set = validator_sets.get(epoch).unwrap(); @@ -241,13 +183,13 @@ pub trait PosReadOnly { /// delegations to their address. fn validator_stake( &self, - validator: &Self::Address, - epoch: impl Into, - ) -> Result { + validator: &Address, + epoch: Epoch, + ) -> Result { let deltas = self.read_validator_deltas(validator)?; let total_stake = deltas.and_then(|deltas| deltas.get(epoch)).and_then( |total_stake| { - let sum: i128 = total_stake.into(); + let sum: i128 = total_stake; let sum: u64 = sum.try_into().ok()?; Some(sum.into()) }, @@ -259,13 +201,13 @@ pub trait PosReadOnly { /// `None`. fn total_stake( &self, - epoch: impl Into, - ) -> Result { - let epoch = epoch.into(); + epoch: Epoch, + ) -> Result { + let epoch = epoch; // TODO read total stake from storage once added self.validator_addresses(epoch)? .into_iter() - .try_fold(Self::TokenAmount::default(), |acc, validator| { + .try_fold(token::Amount::default(), |acc, validator| { Ok(acc + self.validator_stake(&validator, epoch)?) }) } @@ -274,125 +216,104 @@ pub trait PosReadOnly { /// PoS system trait to be implemented in integration that can read and write /// PoS data. pub trait PosActions: PosReadOnly { - /// Error in `PosActions::become_validator` - type BecomeValidatorError: From - + From>; - - /// Error in `PosActions::bond_tokens` - type BondError: From + From>; - - /// Error in `PosActions::unbond_tokens` - type UnbondError: From - + From>; - - /// Error in `PosActions::withdraw_tokens` - type WithdrawError: From + From>; - - /// Error in `PosActions::change_commission_rate` - type CommissionRateChangeError: From - + From>; - /// Write PoS parameters. fn write_pos_params( &mut self, params: &PosParams, - ) -> Result<(), Self::Error>; + ) -> Result<(), storage_api::Error>; /// Write PoS validator's raw hash of its consensus key. fn write_validator_address_raw_hash( &mut self, - address: &Self::Address, - consensus_key: &Self::PublicKey, - ) -> Result<(), Self::Error>; + address: &Address, + consensus_key: &common::PublicKey, + ) -> Result<(), storage_api::Error>; /// Write PoS validator's consensus key (used for signing block votes). fn write_validator_consensus_key( &mut self, - key: &Self::Address, - value: ValidatorConsensusKeys, - ) -> Result<(), Self::Error>; + key: &Address, + value: ValidatorConsensusKeys, + ) -> Result<(), storage_api::Error>; /// Write PoS validator's state. fn write_validator_state( &mut self, - key: &Self::Address, + key: &Address, value: ValidatorStates, - ) -> Result<(), Self::Error>; + ) -> Result<(), storage_api::Error>; /// Write PoS validator's commission rate for delegator rewards fn write_validator_commission_rate( &mut self, - key: &Self::Address, + key: &Address, value: CommissionRates, - ) -> Result<(), Self::Error>; + ) -> Result<(), storage_api::Error>; /// Write PoS validator's maximum change in the commission rate per epoch fn write_validator_max_commission_rate_change( &mut self, - key: &Self::Address, + key: &Address, value: Decimal, - ) -> Result<(), Self::Error>; + ) -> Result<(), storage_api::Error>; /// Write PoS validator's total deltas of their bonds (validator self-bonds /// and delegations). fn write_validator_deltas( &mut self, - key: &Self::Address, - value: ValidatorDeltas, - ) -> Result<(), Self::Error>; + key: &Address, + value: ValidatorDeltas, + ) -> Result<(), storage_api::Error>; /// Write PoS bond (validator self-bond or a delegation). fn write_bond( &mut self, - key: &BondId, - value: Bonds, - ) -> Result<(), Self::Error>; + key: &BondId, + value: Bonds, + ) -> Result<(), storage_api::Error>; /// Write PoS unbond (unbonded tokens from validator self-bond or a /// delegation). fn write_unbond( &mut self, - key: &BondId, - value: Unbonds, - ) -> Result<(), Self::Error>; + key: &BondId, + value: Unbonds, + ) -> Result<(), storage_api::Error>; /// Write PoS validator set (active and inactive). fn write_validator_set( &mut self, - value: ValidatorSets, - ) -> Result<(), Self::Error>; + value: ValidatorSets, + ) -> Result<(), storage_api::Error>; /// Write PoS total deltas of all validators (active and inactive). fn write_total_deltas( &mut self, - value: TotalDeltas, - ) -> Result<(), Self::Error>; + value: TotalDeltas, + ) -> Result<(), storage_api::Error>; /// Delete an emptied PoS bond (validator self-bond or a delegation). - fn delete_bond( - &mut self, - key: &BondId, - ) -> Result<(), Self::Error>; + fn delete_bond(&mut self, key: &BondId) -> Result<(), storage_api::Error>; /// Delete an emptied PoS unbond (unbonded tokens from validator self-bond /// or a delegation). - fn delete_unbond( - &mut self, - key: &BondId, - ) -> Result<(), Self::Error>; + fn delete_unbond(&mut self, key: &BondId) + -> Result<(), storage_api::Error>; /// Transfer tokens from the `src` to the `dest`. fn transfer( &mut self, - token: &Self::Address, - amount: Self::TokenAmount, - src: &Self::Address, - dest: &Self::Address, - ) -> Result<(), Self::Error>; + token: &Address, + amount: token::Amount, + src: &Address, + dest: &Address, + ) -> Result<(), storage_api::Error>; /// Attempt to update the given account to become a validator. fn become_validator( &mut self, - address: &Self::Address, - consensus_key: &Self::PublicKey, - current_epoch: impl Into, + address: &Address, + consensus_key: &common::PublicKey, + current_epoch: Epoch, commission_rate: Decimal, max_commission_rate_change: Decimal, - ) -> Result<(), Self::BecomeValidatorError> { - let current_epoch = current_epoch.into(); + ) -> Result<(), storage_api::Error> { let params = self.read_pos_params()?; let mut validator_set = self.read_validator_set()?; if self.is_validator(address)? { - Err(BecomeValidatorError::AlreadyValidator(address.clone()))?; + return Err(BecomeValidatorError::AlreadyValidator( + address.clone(), + ) + .into()); } let consensus_key_clone = consensus_key.clone(); let BecomeValidatorData { @@ -433,15 +354,17 @@ pub trait PosActions: PosReadOnly { /// `validator`. fn bond_tokens( &mut self, - source: Option<&Self::Address>, - validator: &Self::Address, - amount: Self::TokenAmount, - current_epoch: impl Into, - ) -> Result<(), Self::BondError> { - let current_epoch = current_epoch.into(); + source: Option<&Address>, + validator: &Address, + amount: token::Amount, + current_epoch: Epoch, + ) -> Result<(), storage_api::Error> { if let Some(source) = source { if source != validator && self.is_validator(source)? { - Err(BondError::SourceMustNotBeAValidator(source.clone()))?; + return Err(BondError::SourceMustNotBeAValidator( + source.clone(), + ) + .into()); } } let params = self.read_pos_params()?; @@ -490,12 +413,11 @@ pub trait PosActions: PosReadOnly { /// the `source` to the `validator`. fn unbond_tokens( &mut self, - source: Option<&Self::Address>, - validator: &Self::Address, - amount: Self::TokenAmount, - current_epoch: impl Into, - ) -> Result<(), Self::UnbondError> { - let current_epoch = current_epoch.into(); + source: Option<&Address>, + validator: &Address, + amount: token::Amount, + current_epoch: Epoch, + ) -> Result<(), storage_api::Error> { let params = self.read_pos_params()?; let source = source.unwrap_or(validator); let bond_id = BondId { @@ -555,11 +477,10 @@ pub trait PosActions: PosReadOnly { /// tokens delegated to the `validator` to the `source`. fn withdraw_tokens( &mut self, - source: Option<&Self::Address>, - validator: &Self::Address, - current_epoch: impl Into, - ) -> Result { - let current_epoch = current_epoch.into(); + source: Option<&Address>, + validator: &Address, + current_epoch: Epoch, + ) -> Result { let params = self.read_pos_params()?; let source = source.unwrap_or(validator); let bond_id = BondId { @@ -611,10 +532,10 @@ pub trait PosActions: PosReadOnly { /// Change the commission rate of a validator fn change_validator_commission_rate( &mut self, - validator: &Self::Address, + validator: &Address, new_rate: Decimal, - current_epoch: impl Into, - ) -> Result<(), Self::CommissionRateChangeError> { + current_epoch: Epoch, + ) -> Result<(), storage_api::Error> { if new_rate < Decimal::ZERO { return Err(CommissionRateChangeError::NegativeRate( new_rate, @@ -622,7 +543,7 @@ pub trait PosActions: PosReadOnly { ) .into()); } - let current_epoch = current_epoch.into(); + let max_change = self .read_validator_max_commission_rate_change(validator) .map_err(|_| { @@ -688,68 +609,12 @@ pub trait PosActions: PosReadOnly { /// PoS system base trait for system initialization on genesis block, updating /// the validator on a new epoch and applying slashes. pub trait PosBase { - /// Address type - type Address: 'static - + Display - + Debug - + Clone - + PartialEq - + Eq - + PartialOrd - + Ord - + Hash - + BorshDeserialize - + BorshSerialize - + BorshSchema; - /// Token amount type - type TokenAmount: 'static - + Display - + Debug - + Default - + Clone - + Copy - + Add - + AddAssign - + Sub - + PartialOrd - + Into - + From - + Into - + SubAssign - + BorshDeserialize - + BorshSerialize - + BorshSchema; - /// Token change type - type TokenChange: 'static - + Display - + Debug - + Default - + Clone - + Copy - + PartialOrd - + Add - + Sub - + From - + From - + Into - + Neg - + BorshDeserialize - + BorshSerialize - + BorshSchema; - /// Cryptographic public key type - type PublicKey: 'static - + Debug - + Clone - + BorshDeserialize - + BorshSerialize - + BorshSchema; - /// Address of the PoS account - const POS_ADDRESS: Self::Address; + const POS_ADDRESS: Address; /// Address of the staking token - fn staking_token_address(&self) -> Self::Address; + fn staking_token_address(&self) -> Address; /// Address of the slash pool, into which slashed tokens are transferred. - const POS_SLASH_POOL_ADDRESS: Self::Address; + const POS_SLASH_POOL_ADDRESS: Address; /// Read PoS parameters. fn read_pos_params(&self) -> PosParams; @@ -757,111 +622,90 @@ pub trait PosBase { fn read_validator_address_raw_hash( &self, raw_hash: impl AsRef, - ) -> Option; + ) -> Option
; /// Read PoS validator's consensus key (used for signing block votes). fn read_validator_consensus_key( &self, - key: &Self::Address, - ) -> Option>; + key: &Address, + ) -> Option; /// Read PoS validator's state. - fn read_validator_state( - &self, - key: &Self::Address, - ) -> Option; + fn read_validator_state(&self, key: &Address) -> Option; /// Read PoS validator's total deltas of their bonds (validator self-bonds /// and delegations). - fn read_validator_deltas( - &self, - key: &Self::Address, - ) -> Option>; + fn read_validator_deltas(&self, key: &Address) -> Option; /// Read PoS slashes applied to a validator. - fn read_validator_slashes(&self, key: &Self::Address) -> Slashes; + fn read_validator_slashes(&self, key: &Address) -> Slashes; /// Read PoS validator's commission rate - fn read_validator_commission_rate( - &self, - key: &Self::Address, - ) -> CommissionRates; + fn read_validator_commission_rate(&self, key: &Address) -> CommissionRates; /// Read PoS validator's maximum commission rate change per epoch fn read_validator_max_commission_rate_change( &self, - key: &Self::Address, + key: &Address, ) -> Decimal; /// Read PoS validator set (active and inactive). - fn read_validator_set(&self) -> ValidatorSets; + fn read_validator_set(&self) -> ValidatorSets; /// Read PoS total deltas of all validators (active and inactive). - fn read_total_deltas(&self) -> TotalDeltas; + fn read_total_deltas(&self) -> TotalDeltas; /// Write PoS parameters. fn write_pos_params(&mut self, params: &PosParams); /// Write PoS validator's raw hash of its consensus key. fn write_validator_address_raw_hash( &mut self, - address: &Self::Address, - consensus_key: &Self::PublicKey, + address: &Address, + consensus_key: &common::PublicKey, ); /// Write PoS validator's consensus key (used for signing block votes). fn write_validator_consensus_key( &mut self, - key: &Self::Address, - value: &ValidatorConsensusKeys, + key: &Address, + value: &ValidatorConsensusKeys, ); /// Write PoS validator's state. - fn write_validator_state( - &mut self, - key: &Self::Address, - value: &ValidatorStates, - ); + fn write_validator_state(&mut self, key: &Address, value: &ValidatorStates); /// Write PoS validator's total deltas of their bonds (validator self-bonds /// and delegations). fn write_validator_deltas( &mut self, - key: &Self::Address, - value: &ValidatorDeltas, + key: &Address, + value: &ValidatorDeltas, ); /// Write PoS validator's commission rate. fn write_validator_commission_rate( &mut self, - key: &Self::Address, + key: &Address, value: &CommissionRates, ); /// Write PoS validator's maximum change in the commission rate. fn write_validator_max_commission_rate_change( &mut self, - key: &Self::Address, + key: &Address, value: &Decimal, ); /// Write (append) PoS slash applied to a validator. - fn write_validator_slash( - &mut self, - validator: &Self::Address, - value: Slash, - ); + fn write_validator_slash(&mut self, validator: &Address, value: Slash); /// Write PoS bond (validator self-bond or a delegation). - fn write_bond( - &mut self, - key: &BondId, - value: &Bonds, - ); + fn write_bond(&mut self, key: &BondId, value: &Bonds); /// Write PoS validator set (active and inactive). - fn write_validator_set(&mut self, value: &ValidatorSets); + fn write_validator_set(&mut self, value: &ValidatorSets); /// Write total deltas in PoS for all validators (active and inactive) - fn write_total_deltas(&mut self, value: &TotalDeltas); + fn write_total_deltas(&mut self, value: &TotalDeltas); /// Credit tokens to the `target` account. This should only be used at /// genesis. fn credit_tokens( &mut self, - token: &Self::Address, - target: &Self::Address, - amount: Self::TokenAmount, + token: &Address, + target: &Address, + amount: token::Amount, ); /// Transfer tokens from the `src` to the `dest`. fn transfer( &mut self, - token: &Self::Address, - amount: Self::TokenAmount, - src: &Self::Address, - dest: &Self::Address, + token: &Address, + amount: token::Amount, + src: &Address, + dest: &Address, ); /// Initialize the PoS system storage data in the genesis block for the @@ -871,17 +715,9 @@ pub trait PosBase { fn init_genesis<'a>( &mut self, params: &'a PosParams, - validators: impl Iterator< - Item = &'a GenesisValidator< - Self::Address, - Self::TokenAmount, - Self::PublicKey, - >, - > + Clone - + 'a, - current_epoch: impl Into, + validators: impl Iterator + Clone + 'a, + current_epoch: Epoch, ) -> Result<(), GenesisError> { - let current_epoch = current_epoch.into(); self.write_pos_params(params); let GenesisData { @@ -934,10 +770,10 @@ pub trait PosBase { /// Calls a closure on each validator update element. fn validator_set_update( &self, - current_epoch: impl Into, - f: impl FnMut(ValidatorSetUpdate), + current_epoch: Epoch, + f: impl FnMut(ValidatorSetUpdate), ) { - let current_epoch: Epoch = current_epoch.into(); + let current_epoch: Epoch = current_epoch; let current_epoch_u64: u64 = current_epoch.into(); // INVARIANT: We can only access the previous epochs data, because // this function is called on a beginning of a new block, before @@ -963,7 +799,7 @@ pub trait PosBase { // validator slots are filled with non-0 voting power validators, but we // still need to guard against it. let active_validators = cur_validators.active.iter().filter_map( - |validator: &WeightedValidator<_>| { + |validator: &WeightedValidator| { // If the validators set from previous epoch contains the same // validator, it means its voting power hasn't changed and hence // doesn't need to updated. @@ -1009,7 +845,7 @@ pub trait PosBase { }, ); let inactive_validators = cur_validators.inactive.iter().filter_map( - |validator: &WeightedValidator| { + |validator: &WeightedValidator| { // If the validators set from previous epoch contains the same // validator, it means its voting power hasn't changed and hence // doesn't need to updated. @@ -1050,14 +886,13 @@ pub trait PosBase { fn slash( &mut self, params: &PosParams, - current_epoch: impl Into, - evidence_epoch: impl Into, + current_epoch: Epoch, + evidence_epoch: Epoch, evidence_block_height: impl Into, slash_type: SlashType, - validator: &Self::Address, - ) -> Result<(), SlashError> { - let current_epoch = current_epoch.into(); - let evidence_epoch = evidence_epoch.into(); + validator: &Address, + ) -> Result<(), SlashError> { + let evidence_epoch = evidence_epoch; let rate = slash_type.get_slash_rate(params); let validator_slash = Slash { epoch: evidence_epoch, @@ -1082,10 +917,10 @@ pub trait PosBase { &mut validator_set, &mut total_deltas, )?; - let slashed_change: i128 = slashed_change.into(); + let slashed_change: i128 = slashed_change; let slashed_amount = u64::try_from(slashed_change) .map_err(|_err| SlashError::InvalidSlashChange(slashed_change))?; - let slashed_amount = Self::TokenAmount::from(slashed_amount); + let slashed_amount = token::Amount::from(slashed_amount); self.write_validator_deltas(validator, &deltas); self.write_validator_slash(validator, validator_slash); @@ -1114,14 +949,14 @@ pub enum GenesisError { #[allow(missing_docs)] #[derive(Error, Debug)] -pub enum BecomeValidatorError { +pub enum BecomeValidatorError { #[error("The given address {0} is already a validator")] AlreadyValidator(Address), } #[allow(missing_docs)] #[derive(Error, Debug)] -pub enum BondError { +pub enum BondError { #[error("The given address {0} is not a validator address")] NotAValidator(Address), #[error( @@ -1139,13 +974,13 @@ pub enum BondError { #[allow(missing_docs)] #[derive(Error, Debug)] -pub enum UnbondError { +pub enum UnbondError { #[error("No bond could be found")] NoBondFound, #[error( "Trying to withdraw more tokens ({0}) than the amount bonded ({0})" )] - UnbondAmountGreaterThanBond(TokenAmount, TokenAmount), + UnbondAmountGreaterThanBond(token::Amount, token::Amount), #[error("No bonds found for the validator {0}")] ValidatorHasNoBonds(Address), #[error("Voting power not found for the validator {0}")] @@ -1158,30 +993,16 @@ pub enum UnbondError { #[allow(missing_docs)] #[derive(Error, Debug)] -pub enum WithdrawError
-where - Address: Display - + Debug - + Clone - + PartialOrd - + Ord - + Hash - + BorshDeserialize - + BorshSerialize - + BorshSchema, -{ +pub enum WithdrawError { #[error("No unbond could be found for {0}")] - NoUnbondFound(BondId
), + NoUnbondFound(BondId), #[error("No unbond may be withdrawn yet for {0}")] - NoWithdrawableUnbond(BondId
), + NoWithdrawableUnbond(BondId), } #[allow(missing_docs)] #[derive(Error, Debug)] -pub enum SlashError
-where - Address: Display + Debug + Clone + PartialOrd + Ord + Hash, -{ +pub enum SlashError { #[error("The validator {0} has no total deltas value")] ValidatorHasNoTotalDeltas(Address), #[error("The validator {0} has no voting power")] @@ -1196,18 +1017,7 @@ where #[allow(missing_docs)] #[derive(Error, Debug)] -pub enum CommissionRateChangeError
-where - Address: Display - + Debug - + Clone - + PartialOrd - + Ord - + Hash - + BorshDeserialize - + BorshSerialize - + BorshSchema, -{ +pub enum CommissionRateChangeError { #[error("Unexpected negative commission rate {0} for validator {1}")] NegativeRate(Decimal, Address), #[error("Rate change of {0} is too large for validator {1}")] @@ -1224,148 +1034,52 @@ where CannotRead(Address), } -struct GenesisData +struct GenesisData where - Validators: Iterator< - Item = Result< - GenesisValidatorData, - GenesisError, - >, - >, - Address: Display - + Debug - + Clone - + Ord - + Hash - + BorshDeserialize - + BorshSerialize - + BorshSchema, - TokenAmount: Debug - + Default - + Clone - + Add - + AddAssign - + BorshDeserialize - + BorshSerialize - + BorshSchema, - TokenChange: Debug - + Copy - + Add - + BorshDeserialize - + BorshSerialize - + BorshSchema, - PK: Debug + Clone + BorshDeserialize + BorshSerialize + BorshSchema, + Validators: Iterator>, { validators: Validators, /// Active and inactive validator sets - validator_set: ValidatorSets
, + validator_set: ValidatorSets, /// The sum of all active and inactive validators' bonded deltas - total_deltas: TotalDeltas, + total_deltas: TotalDeltas, /// The sum of all active and inactive validators' bonded tokens - total_bonded_balance: TokenAmount, + total_bonded_balance: token::Amount, } -struct GenesisValidatorData -where - Address: Display - + Debug - + Clone - + Ord - + Hash - + BorshDeserialize - + BorshSerialize - + BorshSchema, - TokenAmount: Debug - + Default - + Clone - + Add - + AddAssign - + BorshDeserialize - + BorshSerialize - + BorshSchema, - TokenChange: Debug - + Copy - + Add - + BorshDeserialize - + BorshSerialize - + BorshSchema, - PK: Debug + Clone + BorshDeserialize + BorshSerialize + BorshSchema, -{ +struct GenesisValidatorData { address: Address, - consensus_key: ValidatorConsensusKeys, + consensus_key: ValidatorConsensusKeys, commission_rate: CommissionRates, max_commission_rate_change: Decimal, state: ValidatorStates, - deltas: ValidatorDeltas, - bond: (BondId
, Bonds), + deltas: ValidatorDeltas, + bond: (BondId, Bonds), } /// A function that returns genesis data created from the initial validator set. -fn init_genesis<'a, Address, TokenAmount, TokenChange, PK>( +fn init_genesis<'a>( params: &'a PosParams, - validators: impl Iterator> - + Clone - + 'a, + validators: impl Iterator + Clone + 'a, current_epoch: Epoch, ) -> Result< GenesisData< - impl Iterator< - Item = Result< - GenesisValidatorData, - GenesisError, - >, - > + 'a, - Address, - TokenAmount, - TokenChange, - PK, + impl Iterator> + 'a, >, GenesisError, -> -where - Address: 'a - + Display - + Debug - + Clone - + Ord - + Hash - + BorshDeserialize - + BorshSerialize - + BorshSchema, - TokenAmount: 'a - + Debug - + Default - + Clone - + Copy - + Add - + AddAssign - + Into - + BorshDeserialize - + BorshSerialize - + BorshSchema, - TokenChange: 'a - + Debug - + Default - + Copy - + Add - + From - + BorshDeserialize - + BorshSerialize - + BorshSchema, - PK: 'a + Debug + Clone + BorshDeserialize + BorshSerialize + BorshSchema, -{ +> { // Accumulate the validator set and total bonded token balance - let mut active: BTreeSet> = BTreeSet::default(); - let mut total_bonded_delta = TokenChange::default(); - let mut total_bonded_balance = TokenAmount::default(); + let mut active: BTreeSet = BTreeSet::default(); + let mut total_bonded_delta = token::Change::default(); + let mut total_bonded_balance = token::Amount::default(); for GenesisValidator { address, tokens, .. } in validators.clone() { total_bonded_balance += *tokens; // 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; + // i64? (token::Change) + let delta = token::Change::from(*tokens); + total_bonded_delta += delta; active.insert(WeightedValidator { bonded_stake: (*tokens).into(), address: address.clone(), @@ -1373,8 +1087,7 @@ where } // Pop the smallest validators from the active set until its size is under // the limit and insert them into the inactive set - let mut inactive: BTreeSet> = - BTreeSet::default(); + let mut inactive: BTreeSet = BTreeSet::default(); while active.len() > params.max_validator_slots as usize { match active.pop_first_shim() { Some(first) => { @@ -1405,7 +1118,7 @@ where ValidatorState::Candidate, current_epoch, ); - let token_delta = TokenChange::from(*tokens); + let token_delta = token::Change::from(*tokens); let deltas = EpochedDelta::init_at_genesis(token_delta, current_epoch); let bond_id = BondId { @@ -1444,49 +1157,26 @@ where /// A function to apply a slash to byzantine validator. #[allow(clippy::too_many_arguments)] -fn slash( +fn slash( params: &PosParams, current_epoch: Epoch, validator: &Address, slash: &Slash, - validator_deltas: &mut ValidatorDeltas, - validator_set: &mut ValidatorSets
, - total_deltas: &mut TotalDeltas, -) -> Result> -where - Address: Display - + Debug - + Clone - + Ord - + Hash - + BorshDeserialize - + BorshSerialize - + BorshSchema, - TokenChange: Display - + Debug - + Copy - + Default - + Neg - + Add - + Sub - + From - + Into - + PartialOrd - + BorshDeserialize - + BorshSerialize - + BorshSchema, -{ - let current_stake: TokenChange = + validator_deltas: &mut ValidatorDeltas, + validator_set: &mut ValidatorSets, + total_deltas: &mut TotalDeltas, +) -> Result { + let current_stake: token::Change = validator_deltas.get(current_epoch).unwrap_or_default(); - if current_stake < TokenChange::default() { + if current_stake < token::Change::default() { return Err(SlashError::NegativeStake( - current_stake.into(), + current_stake, validator.clone(), )); } - let raw_current_stake: i128 = current_stake.into(); - let slashed_amount: TokenChange = - decimal_mult_i128(slash.rate, raw_current_stake).into(); + let raw_current_stake: i128 = current_stake; + let slashed_amount: token::Change = + decimal_mult_i128(slash.rate, raw_current_stake); let token_change = -slashed_amount; // Apply slash at pipeline offset @@ -1524,53 +1214,24 @@ where Ok(slashed_amount) } -struct BecomeValidatorData -where - PK: Debug + Clone + BorshDeserialize + BorshSerialize + BorshSchema, - TokenChange: Default - + Debug - + Clone - + Copy - + Add - + BorshDeserialize - + BorshSerialize - + BorshSchema, -{ - consensus_key: ValidatorConsensusKeys, +struct BecomeValidatorData { + consensus_key: ValidatorConsensusKeys, state: ValidatorStates, - deltas: ValidatorDeltas, + deltas: ValidatorDeltas, commission_rate: Decimal, max_commission_rate_change: Decimal, } /// A function that initialized data for a new validator. -fn become_validator( +fn become_validator( params: &PosParams, address: &Address, - consensus_key: &PK, - validator_set: &mut ValidatorSets
, + consensus_key: &common::PublicKey, + validator_set: &mut ValidatorSets, current_epoch: Epoch, commission_rate: Decimal, max_commission_rate_change: Decimal, -) -> BecomeValidatorData -where - Address: Debug - + Clone - + Ord - + Hash - + BorshDeserialize - + BorshSerialize - + BorshSchema, - PK: Debug + Clone + BorshDeserialize + BorshSerialize + BorshSchema, - TokenChange: Default - + Debug - + Clone - + Copy - + Add - + BorshDeserialize - + BorshSerialize - + BorshSchema, -{ +) -> BecomeValidatorData { let consensus_key = Epoched::init(consensus_key.clone(), current_epoch, params); @@ -1612,81 +1273,25 @@ where } } -struct BondData -where - TokenAmount: Debug - + Default - + Clone - + Copy - + Add - + AddAssign - + BorshDeserialize - + BorshSerialize - + BorshSchema, - TokenChange: Debug - + Clone - + Copy - + Add - + BorshDeserialize - + BorshSerialize - + BorshSchema, -{ - pub bond: Bonds, - pub validator_deltas: ValidatorDeltas, +struct BondData { + pub bond: Bonds, + pub validator_deltas: ValidatorDeltas, } /// Bond tokens to a validator (self-bond or delegation). #[allow(clippy::too_many_arguments)] -fn bond_tokens( +fn bond_tokens( params: &PosParams, validator_state: Option, - bond_id: &BondId
, - current_bond: Option>, - amount: TokenAmount, - validator_deltas: Option>, - total_deltas: &mut TotalDeltas, - validator_set: &mut ValidatorSets
, + bond_id: &BondId, + current_bond: Option, + amount: token::Amount, + validator_deltas: Option, + total_deltas: &mut TotalDeltas, + validator_set: &mut ValidatorSets, current_epoch: Epoch, -) -> Result, BondError
> -where - Address: Display - + Debug - + Clone - + PartialEq - + Eq - + PartialOrd - + Ord - + Hash - + BorshDeserialize - + BorshSerialize - + BorshSchema, - TokenAmount: Display - + Debug - + Default - + Clone - + Copy - + PartialEq - + Add - + AddAssign - + Into - + BorshDeserialize - + BorshSerialize - + BorshSchema, - TokenChange: Display - + Debug - + Default - + Clone - + Copy - + Neg - + Add - + Sub - + From - + Into - + BorshDeserialize - + BorshSerialize - + BorshSchema, -{ - if amount == TokenAmount::default() { +) -> Result { + if amount == token::Amount::default() { return Err(BondError::ZeroAmount); } // Check the validator state @@ -1715,7 +1320,7 @@ where // let mut value = Bond { pos_deltas: HashMap::default(), - neg_deltas: TokenAmount::default(), + neg_deltas: token::Amount::default(), }; // Initialize the bond at the pipeline offset let update_offset = DynEpochOffset::PipelineLen; @@ -1738,7 +1343,7 @@ where // Update validator set. This has to be done before we update the // `validator_deltas`, because we need to look-up the validator with // its voting power before the change. - let token_change = TokenChange::from(amount); + let token_change = token::Change::from(amount); update_validator_set( params, &bond_id.validator, @@ -1750,7 +1355,7 @@ where ); // Update validator's total deltas and total staked token deltas - let delta = TokenChange::from(amount); + let delta = token::Change::from(amount); let validator_deltas = match validator_deltas { Some(mut validator_deltas) => { validator_deltas.add_at_offset( @@ -1777,77 +1382,25 @@ where }) } -struct UnbondData -where - TokenAmount: Debug - + Default - + Clone - + Copy - + Add - + AddAssign - + BorshDeserialize - + BorshSerialize - + BorshSchema, -{ - pub unbond: Unbonds, +struct UnbondData { + pub unbond: Unbonds, } /// Unbond tokens from a validator's bond (self-bond or delegation). #[allow(clippy::too_many_arguments)] -fn unbond_tokens( +fn unbond_tokens( params: &PosParams, - bond_id: &BondId
, - bond: &mut Bonds, - unbond: Option>, - amount: TokenAmount, + bond_id: &BondId, + bond: &mut Bonds, + unbond: Option, + amount: token::Amount, slashes: Slashes, - validator_deltas: &mut ValidatorDeltas, - total_deltas: &mut TotalDeltas, - validator_set: &mut ValidatorSets
, + validator_deltas: &mut ValidatorDeltas, + total_deltas: &mut TotalDeltas, + validator_set: &mut ValidatorSets, current_epoch: Epoch, -) -> Result, UnbondError> -where - Address: Display - + Debug - + Clone - + PartialEq - + Eq - + PartialOrd - + Ord - + Hash - + BorshDeserialize - + BorshSerialize - + BorshSchema, - TokenAmount: Display - + Debug - + Default - + Clone - + Copy - + PartialOrd - + Add - + AddAssign - + Into - + From - + Sub - + SubAssign - + BorshDeserialize - + BorshSerialize - + BorshSchema, - TokenChange: Display - + Debug - + Default - + Clone - + Copy - + Add - + Sub - + From - + Neg - + Into - + BorshDeserialize - + BorshSerialize - + BorshSchema, -{ - if amount == TokenAmount::default() { +) -> Result { + if amount == token::Amount::default() { return Err(UnbondError::ZeroAmount); } // We can unbond tokens that are bonded for a future epoch (not yet @@ -1871,7 +1424,7 @@ where let update_offset = DynEpochOffset::UnbondingLen; let mut to_unbond = amount; let to_unbond = &mut to_unbond; - let mut slashed_amount = TokenAmount::default(); + let mut slashed_amount = token::Amount::default(); // Decrement the bond deltas starting from the rightmost value (a bond in a // future-most epoch) until whole amount is decremented bond.rev_while( @@ -1905,7 +1458,7 @@ where let raw_slashed_delta = decimal_mult_u64(slash.rate, raw_delta); let slashed_delta = - TokenAmount::from(raw_slashed_delta); + token::Amount::from(raw_slashed_delta); slashed_bond_delta -= slashed_delta; } } @@ -1934,7 +1487,7 @@ where // Update validator set. This has to be done before we update the // `validator_deltas`, because we need to look-up the validator with // its voting power before the change. - let token_change = -TokenChange::from(slashed_amount); + let token_change = -token::Change::from(slashed_amount); update_validator_set( params, &bond_id.validator, @@ -1957,38 +1510,15 @@ where /// Update validator set when a validator's receives a new bond and when its /// bond is unbonded (self-bond or delegation). -fn update_validator_set( +fn update_validator_set( params: &PosParams, validator: &Address, - token_change: TokenChange, + token_change: token::Change, change_offset: DynEpochOffset, - validator_set: &mut ValidatorSets
, - validator_deltas: Option<&ValidatorDeltas>, + validator_set: &mut ValidatorSets, + validator_deltas: Option<&ValidatorDeltas>, current_epoch: Epoch, -) where - Address: Display - + Debug - + Clone - + PartialEq - + Eq - + PartialOrd - + Ord - + Hash - + BorshDeserialize - + BorshSerialize - + BorshSchema, - TokenChange: Display - + Default - + Debug - + Clone - + Copy - + Add - + Sub - + Into - + BorshDeserialize - + BorshSerialize - + BorshSchema, -{ +) { validator_set.update_from_offset( |validator_set, epoch| { // Find the validator's bonded stake at the epoch that's being @@ -1997,8 +1527,8 @@ fn update_validator_set( .and_then(|d| d.get(epoch)) .unwrap_or_default(); let tokens_post = tokens_pre + token_change; - let tokens_pre: i128 = tokens_pre.into(); - let tokens_post: i128 = tokens_post.into(); + let tokens_pre: i128 = tokens_pre; + let tokens_post: i128 = tokens_post; let tokens_pre: u64 = TryFrom::try_from(tokens_pre).unwrap(); let tokens_post: u64 = TryFrom::try_from(tokens_post).unwrap(); @@ -2064,75 +1594,37 @@ fn update_validator_set( ) } -struct WithdrawData -where - TokenAmount: Debug - + Default - + Clone - + Copy - + Add - + AddAssign - + BorshDeserialize - + BorshSerialize - + BorshSchema, -{ - pub unbond: Unbonds, - pub withdrawn: TokenAmount, - pub slashed: TokenAmount, +struct WithdrawData { + pub unbond: Unbonds, + pub withdrawn: token::Amount, + pub slashed: token::Amount, } /// Withdraw tokens from unbonds of self-bonds or delegations. -fn withdraw_unbonds( +fn withdraw_unbonds( params: &PosParams, - bond_id: &BondId
, - unbond: Option>, + bond_id: &BondId, + unbond: Option, slashes: Vec, current_epoch: Epoch, -) -> Result, WithdrawError
> -where - Address: Display - + Debug - + Clone - + PartialEq - + Eq - + PartialOrd - + Ord - + Hash - + BorshDeserialize - + BorshSerialize - + BorshSchema, - TokenAmount: Display - + Debug - + Default - + Clone - + Copy - + PartialOrd - + Add - + AddAssign - + Into - + From - + SubAssign - + BorshDeserialize - + BorshSerialize - + BorshSchema, -{ +) -> Result { let mut unbond = unbond.ok_or_else(|| WithdrawError::NoUnbondFound(bond_id.clone()))?; let withdrawable_unbond = unbond .get(current_epoch) .ok_or_else(|| WithdrawError::NoWithdrawableUnbond(bond_id.clone()))?; - let mut slashed = TokenAmount::default(); + let mut slashed = token::Amount::default(); let withdrawn_amount = withdrawable_unbond.deltas.iter().fold( - TokenAmount::default(), + token::Amount::default(), |sum, ((epoch_start, epoch_end), delta)| { let mut delta = *delta; // Check and apply slashes, if any for slash in &slashes { if slash.epoch >= *epoch_start && slash.epoch <= *epoch_end { let raw_delta: u64 = delta.into(); - let current_slashed = TokenAmount::from(decimal_mult_u64( - slash.rate, raw_delta, - )); + let current_slashed = token::Amount::from( + decimal_mult_u64(slash.rate, raw_delta), + ); slashed += current_slashed; delta -= current_slashed; } @@ -2148,56 +1640,32 @@ where }) } -impl From> - for storage_api::Error -{ - fn from( - err: BecomeValidatorError, - ) -> Self { +impl From for storage_api::Error { + fn from(err: BecomeValidatorError) -> Self { Self::new(err) } } -impl From> - for storage_api::Error -{ - fn from(err: BondError) -> Self { +impl From for storage_api::Error { + fn from(err: BondError) -> Self { Self::new(err) } } -impl - From< - UnbondError< - namada_core::types::address::Address, - namada_core::types::token::Amount, - >, - > for storage_api::Error -{ - fn from( - err: UnbondError< - namada_core::types::address::Address, - namada_core::types::token::Amount, - >, - ) -> Self { +impl From for storage_api::Error { + fn from(err: UnbondError) -> Self { Self::new(err) } } -impl From> - for storage_api::Error -{ - fn from(err: WithdrawError) -> Self { +impl From for storage_api::Error { + fn from(err: WithdrawError) -> Self { Self::new(err) } } -impl From> - for storage_api::Error -{ - fn from( - err: CommissionRateChangeError, - ) -> Self { +impl From for storage_api::Error { + fn from(err: CommissionRateChangeError) -> Self { Self::new(err) } } diff --git a/proof_of_stake/src/storage.rs b/proof_of_stake/src/storage.rs index c1c0de49ec..9ba199e449 100644 --- a/proof_of_stake/src/storage.rs +++ b/proof_of_stake/src/storage.rs @@ -2,7 +2,6 @@ use namada_core::ledger::storage::types::{decode, encode}; use namada_core::ledger::storage::{self, Storage, StorageHasher}; -use namada_core::ledger::storage_api; use namada_core::types::address::Address; use namada_core::types::storage::{DbKeySeg, Key, KeySeg}; use namada_core::types::{key, token}; @@ -10,41 +9,9 @@ use rust_decimal::Decimal; use super::ADDRESS; use crate::parameters::PosParams; -pub use crate::types::{CommissionRates, ValidatorStates}; +pub use crate::types::*; use crate::{types, PosBase, PosReadOnly}; -// TODO: these are not needed anymore, remove together with all the generics in -// this crate - -/// Alias for a PoS type with the same name with concrete type parameters -pub type ValidatorConsensusKeys = - crate::types::ValidatorConsensusKeys; - -/// Alias for a PoS type with the same name with concrete type parameters -pub type ValidatorDeltas = crate::types::ValidatorDeltas; - -/// Alias for a PoS type with the same name with concrete type parameters -pub type Bonds = crate::types::Bonds; - -/// Alias for a PoS type with the same name with concrete type parameters -pub type Unbonds = crate::types::Unbonds; - -/// Alias for a PoS type with the same name with concrete type parameters -pub type ValidatorSets = crate::types::ValidatorSets
; - -/// Alias for a PoS type with the same name with concrete type parameters -pub type BondId = crate::types::BondId
; - -/// Alias for a PoS type with the same name with concrete type parameters -pub type GenesisValidator = crate::types::GenesisValidator< - Address, - token::Amount, - key::common::PublicKey, ->; - -/// Alias for a PoS type with the same name with concrete type parameters -pub type TotalDeltas = crate::types::TotalDeltas; - const PARAMS_STORAGE_KEY: &str = "params"; const VALIDATOR_STORAGE_PREFIX: &str = "validator"; const VALIDATOR_ADDRESS_RAW_HASH: &str = "address_raw_hash"; @@ -402,15 +369,11 @@ where D: storage::DB + for<'iter> storage::DBIter<'iter>, H: StorageHasher, { - type Address = Address; - type PublicKey = key::common::PublicKey; - type TokenAmount = token::Amount; - type TokenChange = token::Change; + const POS_ADDRESS: namada_core::types::address::Address = super::ADDRESS; + const POS_SLASH_POOL_ADDRESS: namada_core::types::address::Address = + super::SLASH_POOL_ADDRESS; - const POS_ADDRESS: Self::Address = super::ADDRESS; - const POS_SLASH_POOL_ADDRESS: Self::Address = super::SLASH_POOL_ADDRESS; - - fn staking_token_address(&self) -> Self::Address { + fn staking_token_address(&self) -> namada_core::types::address::Address { self.native_token.clone() } @@ -422,7 +385,7 @@ where fn read_validator_address_raw_hash( &self, raw_hash: impl AsRef, - ) -> Option { + ) -> Option { let (value, _gas) = self .read(&validator_address_raw_hash_key(raw_hash)) .unwrap(); @@ -431,7 +394,7 @@ where fn read_validator_consensus_key( &self, - key: &Self::Address, + key: &namada_core::types::address::Address, ) -> Option { let (value, _gas) = self.read(&validator_consensus_key_key(key)).unwrap(); @@ -440,7 +403,7 @@ where fn read_validator_state( &self, - key: &Self::Address, + key: &namada_core::types::address::Address, ) -> Option { let (value, _gas) = self.read(&validator_state_key(key)).unwrap(); value.map(|value| decode(value).unwrap()) @@ -448,13 +411,16 @@ where fn read_validator_deltas( &self, - key: &Self::Address, - ) -> Option> { + key: &namada_core::types::address::Address, + ) -> Option { let (value, _gas) = self.read(&validator_deltas_key(key)).unwrap(); value.map(|value| decode(value).unwrap()) } - fn read_validator_slashes(&self, key: &Self::Address) -> types::Slashes { + fn read_validator_slashes( + &self, + key: &namada_core::types::address::Address, + ) -> types::Slashes { let (value, _gas) = self.read(&validator_slashes_key(key)).unwrap(); value .map(|value| decode(value).unwrap()) @@ -463,7 +429,7 @@ where fn read_validator_commission_rate( &self, - key: &Self::Address, + key: &namada_core::types::address::Address, ) -> CommissionRates { let (value, _gas) = self.read(&validator_commission_rate_key(key)).unwrap(); @@ -472,7 +438,7 @@ where fn read_validator_max_commission_rate_change( &self, - key: &Self::Address, + key: &namada_core::types::address::Address, ) -> Decimal { let (value, _gas) = self .read(&validator_max_commission_rate_change_key(key)) @@ -496,8 +462,8 @@ where fn write_validator_address_raw_hash( &mut self, - address: &Self::Address, - consensus_key: &Self::PublicKey, + address: &namada_core::types::address::Address, + consensus_key: &namada_core::types::key::common::PublicKey, ) { let raw_hash = key::tm_consensus_key_raw_hash(consensus_key); self.write(&validator_address_raw_hash_key(raw_hash), encode(address)) @@ -506,7 +472,7 @@ where fn write_validator_commission_rate( &mut self, - key: &Self::Address, + key: &namada_core::types::address::Address, value: &CommissionRates, ) { self.write(&validator_commission_rate_key(key), encode(value)) @@ -515,7 +481,7 @@ where fn write_validator_max_commission_rate_change( &mut self, - key: &Self::Address, + key: &namada_core::types::address::Address, value: &rust_decimal::Decimal, ) { self.write( @@ -527,7 +493,7 @@ where fn write_validator_consensus_key( &mut self, - key: &Self::Address, + key: &namada_core::types::address::Address, value: &ValidatorConsensusKeys, ) { self.write(&validator_consensus_key_key(key), encode(value)) @@ -536,7 +502,7 @@ where fn write_validator_state( &mut self, - key: &Self::Address, + key: &namada_core::types::address::Address, value: &ValidatorStates, ) { self.write(&validator_state_key(key), encode(value)) @@ -545,7 +511,7 @@ where fn write_validator_deltas( &mut self, - key: &Self::Address, + key: &namada_core::types::address::Address, value: &ValidatorDeltas, ) { self.write(&validator_deltas_key(key), encode(value)) @@ -554,7 +520,7 @@ where fn write_validator_slash( &mut self, - validator: &Self::Address, + validator: &namada_core::types::address::Address, value: types::Slash, ) { let mut slashes = PosBase::read_validator_slashes(self, validator); @@ -577,9 +543,9 @@ where fn credit_tokens( &mut self, - token: &Self::Address, - target: &Self::Address, - amount: Self::TokenAmount, + token: &namada_core::types::address::Address, + target: &namada_core::types::address::Address, + amount: namada_core::types::token::Amount, ) { let key = token::balance_key(token, target); let new_balance = match self @@ -587,7 +553,7 @@ where .expect("Unable to read token balance for PoS system") { (Some(balance), _gas) => { - let balance: Self::TokenAmount = + let balance: namada_core::types::token::Amount = decode(balance).unwrap_or_default(); balance + amount } @@ -599,10 +565,10 @@ where fn transfer( &mut self, - token: &Self::Address, - amount: Self::TokenAmount, - src: &Self::Address, - dest: &Self::Address, + token: &namada_core::types::address::Address, + amount: namada_core::types::token::Amount, + src: &namada_core::types::address::Address, + dest: &namada_core::types::address::Address, ) { let src_key = token::balance_key(token, src); let dest_key = token::balance_key(token, dest); @@ -610,7 +576,7 @@ where .read(&src_key) .expect("Unable to read token balance for PoS system") { - let mut src_balance: Self::TokenAmount = + let mut src_balance: namada_core::types::token::Amount = decode(src_balance).unwrap_or_default(); if src_balance < amount { tracing::error!( @@ -623,9 +589,10 @@ where } src_balance.spend(&amount); let (dest_balance, _gas) = self.read(&dest_key).unwrap_or_default(); - let mut dest_balance: Self::TokenAmount = dest_balance - .and_then(|b| decode(b).ok()) - .unwrap_or_default(); + let mut dest_balance: namada_core::types::token::Amount = + dest_balance + .and_then(|b| decode(b).ok()) + .unwrap_or_default(); dest_balance.receive(&amount); self.write(&src_key, encode(&src_balance)) .expect("Unable to write token balance for PoS system"); @@ -654,37 +621,28 @@ where #[macro_export] macro_rules! impl_pos_read_only { ( - // Type error type has to be declared before the impl. - // This error type must `impl From for $error`. - type $error:tt = $err_ty:ty ; // Matches anything, so that we can use lifetimes and generic types. // This expects `impl(<.*>)? PoSReadOnly for $ty(<.*>)?`. $( $any:tt )* ) => { $( $any )* { - type Address = namada_core::types::address::Address; - type $error = $err_ty; - type PublicKey = namada_core::types::key::common::PublicKey; - type TokenAmount = namada_core::types::token::Amount; - type TokenChange = namada_core::types::token::Change; - - const POS_ADDRESS: Self::Address = $crate::ADDRESS; + const POS_ADDRESS: namada_core::types::address::Address = $crate::ADDRESS; - fn staking_token_address(&self) -> Self::Address { + fn staking_token_address(&self) -> namada_core::types::address::Address { namada_core::ledger::storage_api::StorageRead::get_native_token(self) .expect("Native token must be available") } - fn read_pos_params(&self) -> std::result::Result { + fn read_pos_params(&self) -> namada_core::ledger::storage_api::Result { let value = namada_core::ledger::storage_api::StorageRead::read_bytes(self, ¶ms_key())?.unwrap(); Ok(namada_core::ledger::storage::types::decode(value).unwrap()) } fn read_validator_consensus_key( &self, - key: &Self::Address, - ) -> std::result::Result, Self::Error> { + key: &namada_core::types::address::Address, + ) -> namada_core::ledger::storage_api::Result> { let value = namada_core::ledger::storage_api::StorageRead::read_bytes(self, &validator_consensus_key_key(key))?; Ok(value.map(|value| namada_core::ledger::storage::types::decode(value).unwrap())) @@ -692,8 +650,8 @@ macro_rules! impl_pos_read_only { fn read_validator_commission_rate( &self, - key: &Self::Address, - ) -> std::result::Result, Self::Error> { + key: &namada_core::types::address::Address, + ) -> namada_core::ledger::storage_api::Result> { let value = namada_core::ledger::storage_api::StorageRead::read_bytes(self, &validator_commission_rate_key(key))?; Ok(value.map(|value| namada_core::ledger::storage::types::decode(value).unwrap())) @@ -701,8 +659,8 @@ macro_rules! impl_pos_read_only { fn read_validator_max_commission_rate_change( &self, - key: &Self::Address, - ) -> std::result::Result, Self::Error> { + key: &namada_core::types::address::Address, + ) -> namada_core::ledger::storage_api::Result> { let value = namada_core::ledger::storage_api::StorageRead::read_bytes(self, &validator_max_commission_rate_change_key(key))?; Ok(value.map(|value| namada_core::ledger::storage::types::decode(value).unwrap())) @@ -710,16 +668,16 @@ macro_rules! impl_pos_read_only { fn read_validator_state( &self, - key: &Self::Address, - ) -> std::result::Result, Self::Error> { + key: &namada_core::types::address::Address, + ) -> namada_core::ledger::storage_api::Result> { let value = namada_core::ledger::storage_api::StorageRead::read_bytes(self, &validator_state_key(key))?; Ok(value.map(|value| namada_core::ledger::storage::types::decode(value).unwrap())) } fn read_validator_deltas( &self, - key: &Self::Address, - ) -> std::result::Result, Self::Error> { + key: &namada_core::types::address::Address, + ) -> namada_core::ledger::storage_api::Result> { let value = namada_core::ledger::storage_api::StorageRead::read_bytes(self, &validator_deltas_key(key))?; Ok(value.map(|value| namada_core::ledger::storage::types::decode(value).unwrap())) @@ -727,8 +685,8 @@ macro_rules! impl_pos_read_only { fn read_validator_slashes( &self, - key: &Self::Address, - ) -> std::result::Result, Self::Error> { + key: &namada_core::types::address::Address, + ) -> namada_core::ledger::storage_api::Result> { let value = namada_core::ledger::storage_api::StorageRead::read_bytes(self, &validator_slashes_key(key))?; Ok(value .map(|value| namada_core::ledger::storage::types::decode(value).unwrap()) @@ -738,7 +696,7 @@ macro_rules! impl_pos_read_only { fn read_bond( &self, key: &BondId, - ) -> std::result::Result, Self::Error> { + ) -> namada_core::ledger::storage_api::Result> { let value = namada_core::ledger::storage_api::StorageRead::read_bytes(self, &bond_key(key))?; Ok(value.map(|value| namada_core::ledger::storage::types::decode(value).unwrap())) } @@ -746,14 +704,14 @@ macro_rules! impl_pos_read_only { fn read_unbond( &self, key: &BondId, - ) -> std::result::Result, Self::Error> { + ) -> namada_core::ledger::storage_api::Result> { let value = namada_core::ledger::storage_api::StorageRead::read_bytes(self, &unbond_key(key))?; Ok(value.map(|value| namada_core::ledger::storage::types::decode(value).unwrap())) } fn read_validator_set( &self, - ) -> std::result::Result { + ) -> namada_core::ledger::storage_api::Result { let value = namada_core::ledger::storage_api::StorageRead::read_bytes(self, &validator_set_key())?.unwrap(); Ok(namada_core::ledger::storage::types::decode(value).unwrap()) @@ -761,7 +719,7 @@ macro_rules! impl_pos_read_only { fn read_total_deltas( &self, - ) -> std::result::Result { + ) -> namada_core::ledger::storage_api::Result { let value = namada_core::ledger::storage_api::StorageRead::read_bytes(self, &total_deltas_key())?.unwrap(); Ok(namada_core::ledger::storage::types::decode(value).unwrap()) @@ -771,7 +729,6 @@ macro_rules! impl_pos_read_only { } impl_pos_read_only! { - type Error = storage_api::Error; impl PosReadOnly for Storage where DB: storage::DB + for<'iter> storage::DBIter<'iter> +'static, diff --git a/proof_of_stake/src/types.rs b/proof_of_stake/src/types.rs index 63832ad4f5..b4e98a42ea 100644 --- a/proof_of_stake/src/types.rs +++ b/proof_of_stake/src/types.rs @@ -5,10 +5,13 @@ use std::collections::{BTreeSet, HashMap}; use std::convert::TryFrom; use std::fmt::Display; use std::hash::Hash; -use std::ops::{Add, AddAssign, Sub}; +use std::ops::Add; use borsh::{BorshDeserialize, BorshSchema, BorshSerialize}; -pub use namada_core::types::storage::Epoch; +use namada_core::types::address::Address; +use namada_core::types::key::common; +use namada_core::types::storage::Epoch; +use namada_core::types::token; use rust_decimal::prelude::{Decimal, ToPrimitive}; use crate::epoched::{ @@ -17,26 +20,20 @@ use crate::epoched::{ use crate::parameters::PosParams; /// Epoched validator's consensus key. -pub type ValidatorConsensusKeys = - Epoched; +pub type ValidatorConsensusKeys = Epoched; /// Epoched validator's state. pub type ValidatorStates = Epoched; /// Epoched validator's total deltas. -pub type ValidatorDeltas = - EpochedDelta; +pub type ValidatorDeltas = EpochedDelta; /// Epoched bond. -pub type Bonds = - EpochedDelta, OffsetUnbondingLen>; +pub type Bonds = EpochedDelta; /// Epoched unbond. -pub type Unbonds = - EpochedDelta, OffsetUnbondingLen>; +pub type Unbonds = EpochedDelta; /// Epoched validator set. -pub type ValidatorSets
= - Epoched, OffsetUnbondingLen>; +pub type ValidatorSets = Epoched; /// Epoched total deltas. -pub type TotalDeltas = - EpochedDelta; +pub type TotalDeltas = EpochedDelta; /// Epoched validator commission rate pub type CommissionRates = Epoched; @@ -52,13 +49,13 @@ pub type CommissionRates = Epoched; PartialOrd, Ord, )] -pub struct GenesisValidator { +pub struct GenesisValidator { /// Validator's address pub address: Address, /// Staked tokens are put into a self-bond - pub tokens: Token, + pub tokens: token::Amount, /// A public key used for signing validator's consensus actions - pub consensus_key: PK, + pub consensus_key: common::PublicKey, /// Commission rate charged on rewards for delegators (bounded inside 0-1) pub commission_rate: Decimal, /// Maximum change in commission rate permitted per epoch @@ -67,18 +64,18 @@ pub struct GenesisValidator { /// An update of the active and inactive validator set. #[derive(Debug, Clone)] -pub enum ValidatorSetUpdate { +pub enum ValidatorSetUpdate { /// A validator is active - Active(ActiveValidator), + Active(ActiveValidator), /// A validator who was active in the last update and is now inactive - Deactivated(PK), + Deactivated(common::PublicKey), } /// Active validator's consensus key and its bonded stake. #[derive(Debug, Clone)] -pub struct ActiveValidator { +pub struct ActiveValidator { /// A public key used for signing validator's consensus actions - pub consensus_key: PK, + pub consensus_key: common::PublicKey, /// Total bonded stake of the validator pub bonded_stake: u64, } @@ -96,20 +93,7 @@ pub struct ActiveValidator { BorshSerialize, BorshSchema, )] -pub struct BondId
-where - Address: Display - + Debug - + Clone - + PartialEq - + Eq - + PartialOrd - + Ord - + Hash - + BorshSerialize - + BorshSchema - + BorshDeserialize, -{ +pub struct BondId { /// (Un)bond's source address is the owner of the bonded tokens. pub source: Address, /// (Un)bond's validator address. @@ -128,19 +112,7 @@ where BorshSerialize, BorshSchema, )] -pub struct WeightedValidator
-where - Address: Debug - + Clone - + PartialEq - + Eq - + PartialOrd - + Ord - + Hash - + BorshDeserialize - + BorshSchema - + BorshSerialize, -{ +pub struct WeightedValidator { /// The `total_stake` field must be on top, because lexicographic ordering /// is based on the top-to-bottom declaration order and in the /// `ValidatorSet` the `WeightedValidator`s these need to be sorted by @@ -150,20 +122,7 @@ where pub address: Address, } -impl
Display for WeightedValidator
-where - Address: Display - + Debug - + Clone - + PartialEq - + Eq - + PartialOrd - + Ord - + Hash - + BorshDeserialize - + BorshSchema - + BorshSerialize, -{ +impl Display for WeightedValidator { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!( f, @@ -185,24 +144,12 @@ where BorshSerialize, BorshSchema, )] -pub struct ValidatorSet
-where - Address: Debug - + Clone - + PartialEq - + Eq - + PartialOrd - + Ord - + Hash - + BorshDeserialize - + BorshSchema - + BorshSerialize, -{ +pub struct ValidatorSet { /// Active validator set with maximum size equal to `max_validator_slots` /// in [`PosParams`]. - pub active: BTreeSet>, + pub active: BTreeSet, /// All the other validators that are not active - pub inactive: BTreeSet>, + pub inactive: BTreeSet, } /// Validator's state. @@ -232,7 +179,7 @@ pub enum ValidatorState { #[derive( Debug, Clone, Default, BorshDeserialize, BorshSerialize, BorshSchema, )] -pub struct Bond { +pub struct Bond { /// Bonded positive deltas. A key is the epoch set for the bond. This is /// used in unbonding, where it's needed for slash epoch range check. /// @@ -240,11 +187,11 @@ pub struct Bond { /// We only need to keep the start `Epoch` for the Epoched head element /// (i.e. the current epoch data), the rest of the array can be calculated /// from the offset from the head - pub pos_deltas: HashMap, + pub pos_deltas: HashMap, /// Unbonded negative deltas. The values are recorded as positive, but /// should be subtracted when we're finding the total for some given /// epoch. - pub neg_deltas: Token, + pub neg_deltas: token::Amount, } /// An unbond contains unbonded tokens from a validator's self-bond or a @@ -252,11 +199,11 @@ pub struct Bond { #[derive( Debug, Clone, Default, BorshDeserialize, BorshSerialize, BorshSchema, )] -pub struct Unbond { +pub struct Unbond { /// A key is a pair of the epoch of the bond from which a unbond was /// created the epoch of unbonding. This is needed for slash epoch range /// check. - pub deltas: HashMap<(Epoch, Epoch), Token>, + pub deltas: HashMap<(Epoch, Epoch), token::Amount>, } /// A slash applied to validator, to punish byzantine behavior by removing @@ -286,20 +233,7 @@ pub enum SlashType { LightClientAttack, } -impl
Display for BondId
-where - Address: Display - + Debug - + Clone - + PartialEq - + Eq - + PartialOrd - + Ord - + Hash - + BorshSerialize - + BorshDeserialize - + BorshSchema, -{ +impl Display for BondId { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!( f, @@ -309,13 +243,10 @@ where } } -impl Bond -where - Token: Clone + Copy + Add + Sub + Default, -{ +impl Bond { /// Find the sum of all the bonds amounts. - pub fn sum(&self) -> Token { - let pos_deltas_sum: Token = self + pub fn sum(&self) -> token::Amount { + let pos_deltas_sum: token::Amount = self .pos_deltas .iter() .fold(Default::default(), |acc, (_epoch, amount)| acc + *amount); @@ -323,10 +254,7 @@ where } } -impl Add for Bond -where - Token: Clone + AddAssign + Default, -{ +impl Add for Bond { type Output = Self; fn add(mut self, rhs: Self) -> Self::Output { @@ -354,22 +282,16 @@ where } } -impl Unbond -where - Token: Clone + Copy + Add + Default, -{ +impl Unbond { /// Find the sum of all the unbonds amounts. - pub fn sum(&self) -> Token { + pub fn sum(&self) -> token::Amount { self.deltas .iter() .fold(Default::default(), |acc, (_epoch, amount)| acc + *amount) } } -impl Add for Unbond -where - Token: Clone + AddAssign + Default, -{ +impl Add for Unbond { type Output = Self; fn add(mut self, rhs: Self) -> Self::Output { diff --git a/proof_of_stake/src/validation.rs b/proof_of_stake/src/validation.rs index 048004dc04..f6fa285b2b 100644 --- a/proof_of_stake/src/validation.rs +++ b/proof_of_stake/src/validation.rs @@ -3,14 +3,13 @@ use std::borrow::Cow; use std::collections::HashMap; use std::convert::TryFrom; -use std::fmt::{Debug, Display}; -use std::hash::Hash; +use std::fmt::Debug; use std::marker::PhantomData; -use std::ops::{Add, AddAssign, Neg, Sub, SubAssign}; -use borsh::{BorshDeserialize, BorshSchema, BorshSerialize}; -use derivative::Derivative; -use namada_core::types::key::PublicKeyTmRawHash; +use namada_core::types::address::Address; +use namada_core::types::key::{common, PublicKeyTmRawHash}; +use namada_core::types::storage::Epoch; +use namada_core::types::token; use rust_decimal::Decimal; use thiserror::Error; @@ -18,30 +17,14 @@ use crate::btree_set::BTreeSetShims; use crate::epoched::DynEpochOffset; use crate::parameters::PosParams; use crate::types::{ - decimal_mult_i128, decimal_mult_u64, BondId, Bonds, CommissionRates, Epoch, - Slash, Slashes, TotalDeltas, Unbonds, ValidatorConsensusKeys, - ValidatorDeltas, ValidatorSets, ValidatorState, ValidatorStates, - WeightedValidator, + decimal_mult_i128, decimal_mult_u64, BondId, Bonds, CommissionRates, Slash, + Slashes, TotalDeltas, Unbonds, ValidatorConsensusKeys, ValidatorDeltas, + ValidatorSets, ValidatorState, ValidatorStates, WeightedValidator, }; #[allow(missing_docs)] #[derive(Error, Debug)] -pub enum Error -where - Address: Display - + Debug - + Clone - + PartialEq - + Eq - + PartialOrd - + Ord - + Hash - + BorshSerialize - + BorshSchema - + BorshDeserialize, - TokenChange: Debug + Display, - PublicKey: Debug, -{ +pub enum Error { #[error("Unexpectedly missing state value for validator {0}")] ValidatorStateIsRequired(Address), #[error("Invalid new validator state in epoch {0}")] @@ -73,9 +56,9 @@ where {bond_delta}, unbonds Δ {unbond_delta}" )] InvalidBalances { - balance_delta: TokenChange, - bond_delta: TokenChange, - unbond_delta: TokenChange, + balance_delta: token::Change, + bond_delta: token::Change, + unbond_delta: token::Change, }, #[error( "Data must be set or updated in the correct epoch. Got epoch {got}, \ @@ -83,35 +66,23 @@ where )] EpochedDataWrongEpoch { got: u64, expected: Vec }, #[error("Empty bond {0} must be deleted")] - EmptyBond(BondId
), + EmptyBond(BondId), #[error( "Bond ID {id} must start at the correct epoch. Got epoch {got}, \ expected {expected}" )] - InvalidBondStartEpoch { - id: BondId
, - got: u64, - expected: u64, - }, + InvalidBondStartEpoch { id: BondId, got: u64, expected: u64 }, #[error( "Bond ID {id} must be added at the correct epoch. Got epoch {got}, \ expected {expected}" )] - InvalidNewBondEpoch { - id: BondId
, - got: u64, - expected: u64, - }, + InvalidNewBondEpoch { id: BondId, got: u64, expected: u64 }, #[error( "Bond ID {id} must be subtracted at the correct epoch. Got epoch \ {got}, expected {expected}" )] - InvalidNegDeltaEpoch { - id: BondId
, - got: u64, - expected: u64, - }, + InvalidNegDeltaEpoch { id: BondId, got: u64, expected: u64 }, #[error( "Invalid validator {address} sum of total deltas. Total Δ \ @@ -119,15 +90,15 @@ where )] InvalidValidatorTotalDeltasSum { address: Address, - total_delta: TokenChange, - bond_delta: TokenChange, + total_delta: token::Change, + bond_delta: token::Change, }, #[error("Unexpectedly missing validator set value")] MissingValidatorSet, #[error("Validator {0} not found in the validator set in epoch {1}")] - WeightedValidatorNotFound(WeightedValidator
, u64), + WeightedValidatorNotFound(WeightedValidator, u64), #[error("Duplicate validator {0} in the validator set in epoch {1}")] - ValidatorSetDuplicate(WeightedValidator
, u64), + ValidatorSetDuplicate(WeightedValidator, u64), #[error("Validator {0} has an invalid total deltas value {1}")] InvalidValidatorTotalDeltas(Address, i128), #[error("There are too many active validators in the validator set")] @@ -136,14 +107,11 @@ where "An inactive validator {0} has voting power greater than an active \ validator {1}" )] - ValidatorSetOutOfOrder( - WeightedValidator
, - WeightedValidator
, - ), + ValidatorSetOutOfOrder(WeightedValidator, WeightedValidator), #[error("Invalid active validator {0}")] - InvalidActiveValidator(WeightedValidator
), + InvalidActiveValidator(WeightedValidator), #[error("Invalid inactive validator {0}")] - InvalidInactiveValidator(WeightedValidator
), + InvalidInactiveValidator(WeightedValidator), #[error("Unexpectedly missing voting power value for validator {0}")] MissingValidatorVotingPower(Address), #[error("Validator {0} has an invalid voting power value {1}")] @@ -161,7 +129,7 @@ where #[error("Invalid address raw hash update")] InvalidRawHashUpdate, #[error("Invalid new validator {0}, some fields are missing: {1:?}.")] - InvalidNewValidator(Address, NewValidator), + InvalidNewValidator(Address, NewValidator), #[error("New validator {0} has not been added to the validator set.")] NewValidatorMissingInValidatorSet(Address), #[error("Validator set has not been updated for new validators.")] @@ -180,62 +148,24 @@ where /// An update of PoS data. #[derive(Clone, Debug)] -pub enum DataUpdate -where - Address: Display - + Debug - + Clone - + PartialEq - + Eq - + PartialOrd - + Ord - + Hash - + BorshDeserialize - + BorshSerialize - + BorshSchema, - TokenAmount: Clone - + Debug - + Default - + Eq - + Sub - + Add - + AddAssign - + BorshDeserialize - + BorshSerialize - + BorshSchema, - TokenChange: Display - + Debug - + Default - + Clone - + Copy - + Add - + Sub - + From - + Into - + PartialEq - + Eq - + BorshDeserialize - + BorshSerialize - + BorshSchema, - PublicKey: Debug + Clone + BorshDeserialize + BorshSerialize + BorshSchema, -{ +pub enum DataUpdate { /// PoS account's balance update - Balance(Data), + Balance(Data), /// Bond update Bond { /// Bond ID - id: BondId
, + id: BondId, /// Bond prior and posterior state - data: Data>, + data: Data, /// List of slashes applied to the bond's validator slashes: Slashes, }, /// Unbond update Unbond { /// Unbond ID - id: BondId
, + id: BondId, /// Unbond prior and posterior state - data: Data>, + data: Data, /// List of slashes applied to the bond's validator slashes: Slashes, }, @@ -244,12 +174,12 @@ where /// Validator's address address: Address, /// Validator's data update - update: ValidatorUpdate, + update: ValidatorUpdate, }, /// Validator set update - ValidatorSet(Data>), + ValidatorSet(Data), /// Total deltas update - TotalDeltas(Data>), + TotalDeltas(Data), /// Validator's address raw hash ValidatorAddressRawHash { /// Raw hash value @@ -261,28 +191,13 @@ where /// An update of a validator's data. #[derive(Clone, Debug)] -pub enum ValidatorUpdate -where - TokenChange: Display - + Debug - + Default - + Clone - + Copy - + Add - + Sub - + PartialEq - + Eq - + BorshDeserialize - + BorshSerialize - + BorshSchema, - PublicKey: Debug + Clone + BorshDeserialize + BorshSerialize + BorshSchema, -{ +pub enum ValidatorUpdate { /// Validator's state update State(Data), /// Consensus key update - ConsensusKey(Data>), + ConsensusKey(Data), /// Validator deltas update - ValidatorDeltas(Data>), + ValidatorDeltas(Data), /// Commission rate update CommissionRate(Data, Option), /// Maximum commission rate change update @@ -303,12 +218,10 @@ where /// A new validator account initialized in a transaction, which is used to check /// that all the validator's required fields have been written. -#[derive(Clone, Debug, Derivative)] -// https://mcarton.github.io/rust-derivative/latest/Default.html#custom-bound -#[derivative(Default(bound = ""))] -pub struct NewValidator { +#[derive(Clone, Debug, Default)] +pub struct NewValidator { has_state: bool, - has_consensus_key: Option, + has_consensus_key: Option, has_total_deltas: bool, has_address_raw_hash: Option, bonded_stake: u64, @@ -329,67 +242,11 @@ struct Constants { /// Validate the given list of PoS data `changes`. Returns empty list, if all /// the changes are valid. #[must_use] -pub fn validate( +pub fn validate( params: &PosParams, - changes: Vec>, - current_epoch: impl Into, -) -> Vec> -where - Address: Display - + Debug - + Clone - + PartialEq - + Eq - + PartialOrd - + Ord - + Hash - + BorshDeserialize - + BorshSerialize - + BorshSchema, - TokenAmount: Display - + Clone - + Copy - + Debug - + Default - + Eq - + Add - + Sub - + AddAssign - + SubAssign - + Into - + From - + BorshDeserialize - + BorshSerialize - + BorshSchema, - TokenChange: Display - + Debug - + Default - + Clone - + Copy - + Add - + Sub - + Neg - + SubAssign - + AddAssign - + From - + Into - + From - + PartialEq - + Eq - + PartialOrd - + Ord - + BorshDeserialize - + BorshSerialize - + BorshSchema, - PublicKey: Debug - + Clone - + BorshDeserialize - + BorshSerialize - + BorshSchema - + PartialEq - + PublicKeyTmRawHash, -{ - let current_epoch: Epoch = current_epoch.into(); + changes: Vec, + current_epoch: Epoch, +) -> Vec { let pipeline_offset = DynEpochOffset::PipelineLen.value(params); let unbonding_offset = DynEpochOffset::UnbondingLen.value(params); let pipeline_epoch = current_epoch + pipeline_offset; @@ -405,19 +262,17 @@ where let mut errors = vec![]; let Accumulator { - balance_delta, - bond_delta, - unbond_delta, - total_deltas, - total_stake_by_epoch, - validator_set_pre, - validator_set_post, - total_deltas_by_epoch: _, - bonded_stake_by_epoch, - new_validators, - } = Validate::::accumulate_changes( - changes, params, &constants, &mut errors - ); + balance_delta, + bond_delta, + unbond_delta, + total_deltas, + total_stake_by_epoch, + validator_set_pre, + validator_set_post, + total_deltas_by_epoch: _, + bonded_stake_by_epoch, + new_validators, + } = Validate::accumulate_changes(changes, params, &constants, &mut errors); // Check total deltas against bonds for (validator, total_delta) in total_deltas.iter() { @@ -441,7 +296,7 @@ where // Negative unbond delta is from withdrawing, which removes tokens from // unbond, but doesn't affect total deltas. for (validator, delta) in &unbond_delta { - if *delta > TokenChange::default() + if *delta > token::Change::default() && !total_deltas.contains_key(validator) { errors.push(Error::MissingValidatorDeltas(validator.clone())); @@ -734,12 +589,12 @@ where let bond_delta = bond_delta .values() .into_iter() - .fold(TokenChange::default(), |acc, delta| acc + (*delta)); + .fold(token::Change::default(), |acc, delta| acc + (*delta)); // Sum the unbond totals let unbond_delta = unbond_delta .values() .into_iter() - .fold(TokenChange::default(), |acc, delta| acc + (*delta)); + .fold(token::Change::default(), |acc, delta| acc + (*delta)); if balance_delta != bond_delta + unbond_delta { errors.push(Error::InvalidBalances { @@ -752,216 +607,44 @@ where errors } -#[derive(Clone, Debug)] -struct Accumulator -where - Address: Display - + Debug - + Clone - + PartialEq - + Eq - + PartialOrd - + Ord - + Hash - + BorshDeserialize - + BorshSerialize - + BorshSchema, - TokenAmount: Display - + Clone - + Copy - + Debug - + Default - + Eq - + Add - + Sub - + AddAssign - + SubAssign - + Into - + From - + BorshDeserialize - + BorshSerialize - + BorshSchema, - TokenChange: Display - + Debug - + Default - + Clone - + Copy - + Add - + Sub - + Neg - + SubAssign - + AddAssign - + From - + Into - + From - + PartialEq - + Eq - + PartialOrd - + Ord - + BorshDeserialize - + BorshSerialize - + BorshSchema, - PublicKey: Debug, -{ - balance_delta: TokenChange, +#[derive(Clone, Debug, Default)] +struct Accumulator { + balance_delta: token::Change, /// Changes of validators' bonds - bond_delta: HashMap, + bond_delta: HashMap, /// Changes of validators' unbonds - unbond_delta: HashMap, + unbond_delta: HashMap, /// Changes of all validator total deltas (up to `unbonding_epoch`) - total_deltas: HashMap, + total_deltas: HashMap, /// Stake calculated from validator total deltas for each epoch /// in which it has changed (the tuple of values are in pre and post state) total_stake_by_epoch: - HashMap>, + HashMap>, /// Total voting power delta calculated from validators' total deltas - total_deltas_by_epoch: HashMap, - bonded_stake_by_epoch: HashMap>, - validator_set_pre: Option>, - validator_set_post: Option>, - new_validators: HashMap>, -} - -/// Accumulator of storage changes -impl Default - for Accumulator -where - Address: Display - + Debug - + Clone - + PartialEq - + Eq - + PartialOrd - + Ord - + Hash - + BorshDeserialize - + BorshSerialize - + BorshSchema, - TokenAmount: Display - + Clone - + Copy - + Debug - + Default - + Eq - + Add - + Sub - + AddAssign - + SubAssign - + Into - + From - + BorshDeserialize - + BorshSerialize - + BorshSchema, - TokenChange: Display - + Debug - + Default - + Clone - + Copy - + Add - + Sub - + Neg - + SubAssign - + AddAssign - + From - + Into - + From - + PartialEq - + Eq - + PartialOrd - + Ord - + BorshDeserialize - + BorshSerialize - + BorshSchema, - PublicKey: Debug, -{ - fn default() -> Self { - Self { - balance_delta: Default::default(), - bond_delta: Default::default(), - unbond_delta: Default::default(), - total_deltas: Default::default(), - total_stake_by_epoch: Default::default(), - total_deltas_by_epoch: Default::default(), - bonded_stake_by_epoch: Default::default(), - validator_set_pre: Default::default(), - validator_set_post: Default::default(), - new_validators: Default::default(), - } - } + total_deltas_by_epoch: HashMap, + bonded_stake_by_epoch: HashMap>, + validator_set_pre: Option, + validator_set_post: Option, + new_validators: HashMap, } /// An empty local type to re-use trait bounds for the functions associated with /// `Validate` in the `impl` below -struct Validate { +struct Validate { address: PhantomData
, - token_amount: PhantomData, - token_change: PhantomData, - public_key: PhantomData, + token_amount: PhantomData, + token_change: PhantomData, + public_key: PhantomData, } -impl - Validate -where - Address: Display - + Debug - + Clone - + PartialEq - + Eq - + PartialOrd - + Ord - + Hash - + BorshDeserialize - + BorshSerialize - + BorshSchema, - TokenAmount: Display - + Clone - + Copy - + Debug - + Default - + Eq - + Add - + Sub - + AddAssign - + SubAssign - + Into - + From - + BorshDeserialize - + BorshSerialize - + BorshSchema, - TokenChange: Display - + Debug - + Default - + Clone - + Copy - + Add - + Sub - + Neg - + SubAssign - + AddAssign - + From - + Into - + From - + PartialEq - + Eq - + PartialOrd - + Ord - + BorshDeserialize - + BorshSerialize - + BorshSchema, - PublicKey: Debug - + Clone - + BorshDeserialize - + BorshSerialize - + BorshSchema - + PartialEq, -{ +impl Validate { fn accumulate_changes( - changes: Vec>, + changes: Vec, _params: &PosParams, constants: &Constants, - errors: &mut Vec>, - ) -> Accumulator { + errors: &mut Vec, + ) -> Accumulator { use DataUpdate::*; use ValidatorUpdate::*; @@ -1065,8 +748,8 @@ where fn validator_state( constants: &Constants, - errors: &mut Vec>, - new_validators: &mut HashMap>, + errors: &mut Vec, + new_validators: &mut HashMap, address: Address, data: Data, ) { @@ -1140,10 +823,10 @@ where fn validator_consensus_key( constants: &Constants, - errors: &mut Vec>, - new_validators: &mut HashMap>, + errors: &mut Vec, + new_validators: &mut HashMap, address: Address, - data: Data>, + data: Data, ) { match (data.pre, data.post) { (None, Some(post)) => { @@ -1195,15 +878,15 @@ where fn validator_deltas( constants: &Constants, - errors: &mut Vec>, - total_deltas: &mut HashMap, + errors: &mut Vec, + total_deltas: &mut HashMap, total_stake_by_epoch: &mut HashMap< Epoch, - HashMap, + HashMap, >, - new_validators: &mut HashMap>, + new_validators: &mut HashMap, address: Address, - data: Data>, + data: Data, ) { match (data.pre, data.post) { (Some(pre), Some(post)) => { @@ -1211,11 +894,11 @@ where errors.push(Error::InvalidLastUpdate) } // Changes of all total deltas (up to `unbonding_epoch`) - let mut deltas = TokenChange::default(); + let mut deltas = token::Change::default(); // Sum of pre total deltas - let mut pre_deltas_sum = TokenChange::default(); + let mut pre_deltas_sum = token::Change::default(); // Sum of post total deltas - let mut post_deltas_sum = TokenChange::default(); + let mut post_deltas_sum = token::Change::default(); // Iter from the first epoch to the last epoch of `post` for epoch in Epoch::iter_range( constants.current_epoch, @@ -1223,7 +906,7 @@ where ) { // Changes of all total deltas (up to // `unbonding_epoch`) - let mut delta = TokenChange::default(); + let mut delta = token::Change::default(); // Find the delta in `pre` if let Some(change) = { if epoch == constants.current_epoch { @@ -1250,8 +933,9 @@ where u64::try_from(stake_post), ) { (Ok(stake_pre), Ok(stake_post)) => { - let stake_pre = TokenAmount::from(stake_pre); - let stake_post = TokenAmount::from(stake_post); + let stake_pre = token::Amount::from(stake_pre); + let stake_post = + token::Amount::from(stake_post); total_stake_by_epoch .entry(epoch) .or_insert_with(HashMap::default) @@ -1272,7 +956,7 @@ where // A total delta can only be increased at // `pipeline_offset` from bonds and decreased at // `unbonding_offset` from unbonding - if delta > TokenChange::default() + if delta > token::Change::default() && epoch != constants.pipeline_epoch { errors.push(Error::EpochedDataWrongEpoch { @@ -1280,7 +964,7 @@ where expected: vec![constants.pipeline_epoch.into()], }) } - if delta < TokenChange::default() + if delta < token::Change::default() && epoch != constants.unbonding_epoch { errors.push(Error::EpochedDataWrongEpoch { @@ -1289,12 +973,12 @@ where }) } } - if post_deltas_sum < TokenChange::default() { + if post_deltas_sum < token::Change::default() { errors.push(Error::NegativeValidatorDeltasSum( address.clone(), )) } - if deltas != TokenChange::default() { + if deltas != token::Change::default() { let deltas_entry = total_deltas.entry(address).or_default(); *deltas_entry += deltas; } @@ -1304,7 +988,7 @@ where errors.push(Error::InvalidLastUpdate) } // Changes of all total deltas (up to `unbonding_epoch`) - let mut deltas = TokenChange::default(); + let mut deltas = token::Change::default(); for epoch in Epoch::iter_range( constants.current_epoch, constants.unbonding_offset + 1, @@ -1325,7 +1009,7 @@ where let stake: i128 = Into::into(deltas); match u64::try_from(stake) { Ok(stake) => { - let stake = TokenAmount::from(stake); + let stake = token::Amount::from(stake); total_stake_by_epoch .entry(epoch) .or_insert_with(HashMap::default) @@ -1340,12 +1024,12 @@ where } } } - if deltas < TokenChange::default() { + if deltas < token::Change::default() { errors.push(Error::NegativeValidatorDeltasSum( address.clone(), )) } - if deltas != TokenChange::default() { + if deltas != token::Change::default() { let deltas_entry = total_deltas.entry(address.clone()).or_default(); *deltas_entry += deltas; @@ -1365,8 +1049,8 @@ where fn validator_commission_rate( constants: &Constants, - errors: &mut Vec>, - new_validators: &mut HashMap>, + errors: &mut Vec, + new_validators: &mut HashMap, address: Address, data: Data, max_change: Option, @@ -1444,8 +1128,8 @@ where } fn validator_max_commission_rate_change( - errors: &mut Vec>, - new_validators: &mut HashMap>, + errors: &mut Vec, + new_validators: &mut HashMap, address: Address, data: Data, ) { @@ -1468,15 +1152,15 @@ where } fn balance( - errors: &mut Vec>, - balance_delta: &mut TokenChange, - data: Data, + errors: &mut Vec, + balance_delta: &mut token::Change, + data: Data, ) { match (data.pre, data.post) { - (None, Some(post)) => *balance_delta += TokenChange::from(post), + (None, Some(post)) => *balance_delta += token::Change::from(post), (Some(pre), Some(post)) => { *balance_delta += - TokenChange::from(post) - TokenChange::from(pre); + token::Change::from(post) - token::Change::from(pre); } (Some(_), None) => errors.push(Error::MissingBalance), (None, None) => {} @@ -1485,10 +1169,10 @@ where fn bond( constants: &Constants, - errors: &mut Vec>, - bond_delta: &mut HashMap, - id: BondId
, - data: Data>, + errors: &mut Vec, + bond_delta: &mut HashMap, + id: BondId, + data: Data, slashes: Vec, ) { match (data.pre, data.post) { @@ -1511,13 +1195,13 @@ where }; // Pre-bonds keyed by their `start_epoch` - let mut pre_bonds: HashMap = + let mut pre_bonds: HashMap = HashMap::default(); // We have to slash only the difference between post and // pre, not both pre and post to avoid rounding errors - let mut slashed_deltas: HashMap = + let mut slashed_deltas: HashMap = HashMap::default(); - let mut neg_deltas: HashMap = + let mut neg_deltas: HashMap = Default::default(); // Iter from the first epoch of `pre` to the last epoch of // `post` @@ -1527,7 +1211,7 @@ where ) { if let Some(bond) = pre.get_delta_at_epoch(epoch) { for (start_epoch, delta) in bond.pos_deltas.iter() { - let delta = TokenChange::from(*delta); + let delta = token::Change::from(*delta); slashed_deltas.insert(*start_epoch, -delta); pre_bonds.insert(*start_epoch, delta); } @@ -1537,12 +1221,12 @@ where epoch }; let entry = neg_deltas.entry(ins_epoch).or_default(); - *entry -= TokenChange::from(bond.neg_deltas); + *entry -= token::Change::from(bond.neg_deltas); } if let Some(bond) = post.get_delta_at_epoch(epoch) { for (start_epoch, delta) in bond.pos_deltas.iter() { // An empty bond must be deleted - if *delta == TokenAmount::default() { + if *delta == token::Amount::default() { errors.push(Error::EmptyBond(id.clone())) } // On the current epoch, all bond's @@ -1561,10 +1245,10 @@ where expected: epoch.into(), }) } - let delta = TokenChange::from(*delta); + let delta = token::Change::from(*delta); match slashed_deltas.get_mut(start_epoch) { Some(pre_delta) => { - if *pre_delta + delta == 0_i128.into() { + if *pre_delta + delta == 0_i128 { slashed_deltas.remove(start_epoch); } else { *pre_delta += delta; @@ -1617,7 +1301,7 @@ where match neg_deltas.get(&epoch) { Some(deltas) => { if -*deltas - != TokenChange::from(bond.neg_deltas) + != token::Change::from(bond.neg_deltas) { errors.push( Error::InvalidNegDeltaEpoch { @@ -1646,31 +1330,30 @@ where } } let entry = neg_deltas.entry(epoch).or_default(); - *entry += TokenChange::from(bond.neg_deltas); + *entry += token::Change::from(bond.neg_deltas); } } // Check slashes for (start_epoch, delta) in slashed_deltas.iter_mut() { for slash in &slashes { if slash.epoch >= *start_epoch { - let raw_delta: i128 = (*delta).into(); - let current_slashed = TokenChange::from( - decimal_mult_i128(slash.rate, raw_delta), - ); + let raw_delta: i128 = *delta; + let current_slashed = + decimal_mult_i128(slash.rate, raw_delta); *delta -= current_slashed; } } } let total = slashed_deltas .values() - .fold(TokenChange::default(), |acc, delta| acc + *delta) + .fold(token::Change::default(), |acc, delta| acc + *delta) - neg_deltas .values() - .fold(TokenChange::default(), |acc, delta| { + .fold(token::Change::default(), |acc, delta| { acc + *delta }); - if total != TokenChange::default() { + if total != token::Change::default() { let bond_entry = bond_delta.entry(id.validator).or_default(); *bond_entry += total; @@ -1681,7 +1364,7 @@ where if post.last_update() != constants.current_epoch { errors.push(Error::InvalidLastUpdate) } - let mut total_delta = TokenChange::default(); + let mut total_delta = token::Change::default(); for epoch in Epoch::iter_range( constants.current_epoch, constants.unbonding_offset + 1, @@ -1720,20 +1403,20 @@ where for slash in &slashes { if slash.epoch >= *start_epoch { let raw_delta: u64 = delta.into(); - let current_slashed = TokenAmount::from( + let current_slashed = token::Amount::from( decimal_mult_u64(slash.rate, raw_delta), ); delta -= current_slashed; } } - let delta = TokenChange::from(delta); + let delta = token::Change::from(delta); total_delta += delta } - total_delta -= TokenChange::from(bond.neg_deltas) + total_delta -= token::Change::from(bond.neg_deltas) } } // An empty bond must be deleted - if total_delta == TokenChange::default() { + if total_delta == token::Change::default() { errors.push(Error::EmptyBond(id.clone())) } let bond_entry = bond_delta.entry(id.validator).or_default(); @@ -1741,7 +1424,7 @@ where } // Bond may be deleted when all the tokens are unbonded (Some(pre), None) => { - let mut total_delta = TokenChange::default(); + let mut total_delta = token::Change::default(); for index in 0..constants.pipeline_offset + 1 { let index = index as usize; let epoch = pre.last_update() + index; @@ -1752,16 +1435,16 @@ where for slash in &slashes { if slash.epoch >= *start_epoch { let raw_delta: u64 = delta.into(); - let current_slashed = TokenAmount::from( + let current_slashed = token::Amount::from( decimal_mult_u64(slash.rate, raw_delta), ); delta -= current_slashed; } } - let delta = TokenChange::from(delta); + let delta = token::Change::from(delta); total_delta -= delta } - total_delta += TokenChange::from(bond.neg_deltas) + total_delta += token::Change::from(bond.neg_deltas) } } let bond_entry = bond_delta.entry(id.validator).or_default(); @@ -1773,10 +1456,10 @@ where fn unbond( constants: &Constants, - errors: &mut Vec>, - unbond_delta: &mut HashMap, - id: BondId
, - data: Data>, + errors: &mut Vec, + unbond_delta: &mut HashMap, + id: BondId, + data: Data, slashes: Vec, ) { match (data.pre, data.post) { @@ -1800,7 +1483,7 @@ where // We have to slash only the difference between post and // pre, not both pre and post to avoid rounding errors - let mut slashed_deltas: HashMap<(Epoch, Epoch), TokenChange> = + let mut slashed_deltas: HashMap<(Epoch, Epoch), token::Change> = HashMap::default(); // Iter from the first epoch of `pre` to the last epoch of // `post` @@ -1812,7 +1495,7 @@ where for ((start_epoch, end_epoch), delta) in unbond.deltas.iter() { - let delta = TokenChange::from(*delta); + let delta = token::Change::from(*delta); slashed_deltas .insert((*start_epoch, *end_epoch), -delta); } @@ -1821,11 +1504,11 @@ where for ((start_epoch, end_epoch), delta) in unbond.deltas.iter() { - let delta = TokenChange::from(*delta); + let delta = token::Change::from(*delta); let key = (*start_epoch, *end_epoch); match slashed_deltas.get_mut(&key) { Some(pre_delta) => { - if *pre_delta + delta == 0_i128.into() { + if *pre_delta + delta == 0_i128 { slashed_deltas.remove(&key); } else { *pre_delta += delta; @@ -1846,18 +1529,17 @@ where if slash.epoch >= *start_epoch && slash.epoch <= *end_epoch { - let raw_delta: i128 = (*delta).into(); - let current_slashed = TokenChange::from( - decimal_mult_i128(slash.rate, raw_delta), - ); + let raw_delta: i128 = *delta; + let current_slashed = + decimal_mult_i128(slash.rate, raw_delta); *delta -= current_slashed; } } } let total = slashed_deltas .values() - .fold(TokenChange::default(), |acc, delta| acc + *delta); - if total != TokenChange::default() { + .fold(token::Change::default(), |acc, delta| acc + *delta); + if total != token::Change::default() { let unbond_entry = unbond_delta.entry(id.validator).or_default(); *unbond_entry += total; @@ -1868,7 +1550,7 @@ where if post.last_update() != constants.current_epoch { errors.push(Error::InvalidLastUpdate) } - let mut total_delta = TokenChange::default(); + let mut total_delta = token::Change::default(); for epoch in Epoch::iter_range( post.last_update(), constants.unbonding_offset + 1, @@ -1884,13 +1566,13 @@ where && slash.epoch <= *end_epoch { let raw_delta: u64 = delta.into(); - let current_slashed = TokenAmount::from( + let current_slashed = token::Amount::from( decimal_mult_u64(slash.rate, raw_delta), ); delta -= current_slashed; } } - let delta = TokenChange::from(delta); + let delta = token::Change::from(delta); total_delta += delta; } } @@ -1901,7 +1583,7 @@ where } // Unbond may be deleted when all the tokens are withdrawn (Some(pre), None) => { - let mut total_delta = TokenChange::default(); + let mut total_delta = token::Change::default(); for epoch in Epoch::iter_range( pre.last_update(), constants.unbonding_offset + 1, @@ -1917,13 +1599,13 @@ where && slash.epoch <= *end_epoch { let raw_delta: u64 = delta.into(); - let current_slashed = TokenAmount::from( + let current_slashed = token::Amount::from( decimal_mult_u64(slash.rate, raw_delta), ); delta -= current_slashed; } } - let delta = TokenChange::from(delta); + let delta = token::Change::from(delta); total_delta -= delta; } } @@ -1938,10 +1620,10 @@ where fn validator_set( constants: &Constants, - errors: &mut Vec>, - validator_set_pre: &mut Option>, - validator_set_post: &mut Option>, - data: Data>, + errors: &mut Vec, + validator_set_pre: &mut Option, + validator_set_post: &mut Option, + data: Data, ) { match (data.pre, data.post) { (Some(pre), Some(post)) => { @@ -1957,9 +1639,9 @@ where fn total_deltas( constants: &Constants, - errors: &mut Vec>, - total_delta_by_epoch: &mut HashMap, - data: Data>, + errors: &mut Vec, + total_delta_by_epoch: &mut HashMap, + data: Data, ) { match (data.pre, data.post) { (Some(pre), Some(post)) => { @@ -1998,8 +1680,8 @@ where } fn validator_address_raw_hash( - errors: &mut Vec>, - new_validators: &mut HashMap>, + errors: &mut Vec, + new_validators: &mut HashMap, raw_hash: String, data: Data
, ) { diff --git a/shared/src/ledger/pos/mod.rs b/shared/src/ledger/pos/mod.rs index db16c3eebf..2878f89fb2 100644 --- a/shared/src/ledger/pos/mod.rs +++ b/shared/src/ledger/pos/mod.rs @@ -5,9 +5,7 @@ pub mod vp; pub use namada_proof_of_stake; pub use namada_proof_of_stake::parameters::PosParams; pub use namada_proof_of_stake::storage::*; -pub use namada_proof_of_stake::types::{ - self, decimal_mult_u64, Slash, Slashes, ValidatorStates, -}; +pub use namada_proof_of_stake::types; use namada_proof_of_stake::PosBase; use rust_decimal::Decimal; pub use vp::PosVP; @@ -15,7 +13,6 @@ pub use vp::PosVP; use crate::ledger::storage::{self as ledger_storage, Storage, StorageHasher}; use crate::types::address::{Address, InternalAddress}; use crate::types::storage::Epoch; -use crate::types::{key, token}; /// Address of the PoS account implemented as a native VP pub const ADDRESS: Address = Address::Internal(InternalAddress::PoS); @@ -48,38 +45,3 @@ pub fn init_genesis_storage<'a, DB, H>( .init_genesis(params, validators, current_epoch) .expect("Initialize PoS genesis storage") } - -/// Alias for a PoS type with the same name with concrete type parameters -pub type ValidatorConsensusKeys = - namada_proof_of_stake::types::ValidatorConsensusKeys< - key::common::PublicKey, - >; - -/// Alias for a PoS type with the same name with concrete type parameters -pub type ValidatorDeltas = - namada_proof_of_stake::types::ValidatorDeltas; - -/// Alias for a PoS type with the same name with concrete type parameters -pub type Bonds = namada_proof_of_stake::types::Bonds; - -/// Alias for a PoS type with the same name with concrete type parameters -pub type Unbonds = namada_proof_of_stake::types::Unbonds; - -/// Alias for a PoS type with the same name with concrete type parameters -pub type ValidatorSets = namada_proof_of_stake::types::ValidatorSets
; - -/// Alias for a PoS type with the same name with concrete type parameters -pub type BondId = namada_proof_of_stake::types::BondId
; - -/// Alias for a PoS type with the same name with concrete type parameters -pub type GenesisValidator = namada_proof_of_stake::types::GenesisValidator< - Address, - token::Amount, - key::common::PublicKey, ->; - -/// Alias for a PoS type with the same name with concrete type parameters -pub type CommissionRates = namada_proof_of_stake::types::CommissionRates; - -/// Alias for a PoS type with the same name with concrete type parameters -pub type TotalDeltas = namada_proof_of_stake::types::TotalDeltas; diff --git a/shared/src/ledger/pos/vp.rs b/shared/src/ledger/pos/vp.rs index 0094ad9b5c..e1b13648d0 100644 --- a/shared/src/ledger/pos/vp.rs +++ b/shared/src/ledger/pos/vp.rs @@ -32,7 +32,7 @@ use crate::ledger::pos::{ is_validator_max_commission_rate_change_key, is_validator_state_key, }; use crate::ledger::storage::{self as ledger_storage, StorageHasher}; -use crate::ledger::storage_api::{self, StorageRead}; +use crate::ledger::storage_api::StorageRead; use crate::types::address::{Address, InternalAddress}; use crate::types::storage::{Key, KeySeg}; use crate::types::token; @@ -116,7 +116,7 @@ where use validation::ValidatorUpdate::*; let addr = Address::Internal(Self::ADDR); - let mut changes: Vec> = vec![]; + let mut changes: Vec = vec![]; let current_epoch = self.ctx.pre().get_block_epoch()?; let staking_token_address = self.ctx.pre().get_native_token()?; @@ -305,7 +305,6 @@ where } impl_pos_read_only! { - type Error = storage_api::Error; impl<'f, 'a, DB, H, CA> PosReadOnly for CtxPreStorageRead<'f, 'a, DB, H, CA> where DB: ledger_storage::DB + for<'iter> ledger_storage::DBIter<'iter> +'static, @@ -314,7 +313,6 @@ impl_pos_read_only! { } impl_pos_read_only! { - type Error = storage_api::Error; impl<'f, 'a, DB, H, CA> PosReadOnly for CtxPostStorageRead<'f, 'a, DB, H, CA> where DB: ledger_storage::DB + for<'iter> ledger_storage::DBIter<'iter> +'static, diff --git a/tests/src/native_vp/pos.rs b/tests/src/native_vp/pos.rs index aff88abef9..69b7502a50 100644 --- a/tests/src/native_vp/pos.rs +++ b/tests/src/native_vp/pos.rs @@ -126,11 +126,7 @@ pub fn init_pos( // Initialize PoS storage tx_env .storage - .init_genesis( - params, - genesis_validators.iter(), - u64::from(start_epoch), - ) + .init_genesis(params, genesis_validators.iter(), start_epoch) .unwrap(); }); } diff --git a/tx_prelude/src/proof_of_stake.rs b/tx_prelude/src/proof_of_stake.rs index caec03a12c..ec2977b294 100644 --- a/tx_prelude/src/proof_of_stake.rs +++ b/tx_prelude/src/proof_of_stake.rs @@ -1,5 +1,6 @@ //! Proof of Stake system integration with functions for transactions +use namada_core::types::key::common; use namada_core::types::transaction::InitValidator; use namada_core::types::{key, token}; pub use namada_proof_of_stake::parameters::PosParams; @@ -127,70 +128,63 @@ impl Ctx { } namada_proof_of_stake::impl_pos_read_only! { - type Error = crate::Error; impl namada_proof_of_stake::PosReadOnly for Ctx } impl namada_proof_of_stake::PosActions for Ctx { - type BecomeValidatorError = crate::Error; - type BondError = crate::Error; - type CommissionRateChangeError = crate::Error; - type UnbondError = crate::Error; - type WithdrawError = crate::Error; - fn write_pos_params( &mut self, params: &PosParams, - ) -> Result<(), Self::Error> { + ) -> storage_api::Result<()> { self.write(¶ms_key(), params) } fn write_validator_address_raw_hash( &mut self, - address: &Self::Address, - consensus_key: &Self::PublicKey, - ) -> Result<(), Self::Error> { + address: &Address, + consensus_key: &common::PublicKey, + ) -> storage_api::Result<()> { let raw_hash = key::tm_consensus_key_raw_hash(consensus_key); self.write(&validator_address_raw_hash_key(raw_hash), address) } fn write_validator_consensus_key( &mut self, - key: &Self::Address, + key: &Address, value: ValidatorConsensusKeys, - ) -> Result<(), Self::Error> { + ) -> storage_api::Result<()> { self.write(&validator_consensus_key_key(key), &value) } fn write_validator_state( &mut self, - key: &Self::Address, + key: &Address, value: ValidatorStates, - ) -> Result<(), Self::Error> { + ) -> storage_api::Result<()> { self.write(&validator_state_key(key), &value) } fn write_validator_commission_rate( &mut self, - key: &Self::Address, + key: &Address, value: CommissionRates, - ) -> Result<(), Self::Error> { + ) -> storage_api::Result<()> { self.write(&validator_commission_rate_key(key), &value) } fn write_validator_max_commission_rate_change( &mut self, - key: &Self::Address, + key: &Address, value: Decimal, - ) -> Result<(), Self::Error> { + ) -> storage_api::Result<()> { self.write(&validator_max_commission_rate_change_key(key), &value) } fn write_validator_deltas( &mut self, - key: &Self::Address, + key: &Address, value: ValidatorDeltas, - ) -> Result<(), Self::Error> { + ) -> storage_api::Result<()> { self.write(&validator_deltas_key(key), &value) } @@ -198,7 +192,7 @@ impl namada_proof_of_stake::PosActions for Ctx { &mut self, key: &BondId, value: Bonds, - ) -> Result<(), Self::Error> { + ) -> storage_api::Result<()> { self.write(&bond_key(key), &value) } @@ -206,39 +200,39 @@ impl namada_proof_of_stake::PosActions for Ctx { &mut self, key: &BondId, value: Unbonds, - ) -> Result<(), Self::Error> { + ) -> storage_api::Result<()> { self.write(&unbond_key(key), &value) } fn write_validator_set( &mut self, value: ValidatorSets, - ) -> Result<(), Self::Error> { + ) -> storage_api::Result<()> { self.write(&validator_set_key(), &value) } fn write_total_deltas( &mut self, value: TotalDeltas, - ) -> Result<(), Self::Error> { + ) -> storage_api::Result<()> { self.write(&total_deltas_key(), &value) } - fn delete_bond(&mut self, key: &BondId) -> Result<(), Self::Error> { + fn delete_bond(&mut self, key: &BondId) -> storage_api::Result<()> { self.delete(&bond_key(key)) } - fn delete_unbond(&mut self, key: &BondId) -> Result<(), Self::Error> { + fn delete_unbond(&mut self, key: &BondId) -> storage_api::Result<()> { self.delete(&unbond_key(key)) } fn transfer( &mut self, - token: &Self::Address, - amount: Self::TokenAmount, - src: &Self::Address, - dest: &Self::Address, - ) -> Result<(), Self::Error> { + token: &Address, + amount: token::Amount, + src: &Address, + dest: &Address, + ) -> storage_api::Result<()> { crate::token::transfer( self, src, dest, token, None, amount, &None, &None, ) diff --git a/wasm/wasm_source/src/tx_bond.rs b/wasm/wasm_source/src/tx_bond.rs index 894aa40763..5e5eeb474a 100644 --- a/wasm/wasm_source/src/tx_bond.rs +++ b/wasm/wasm_source/src/tx_bond.rs @@ -203,7 +203,7 @@ mod tests { // A delegation is applied at pipeline offset // Check that bond is empty before pipeline offset for epoch in 0..pos_params.pipeline_len { - let bond: Option> = bonds_post.get(epoch); + let bond: Option = bonds_post.get(epoch); assert!( bond.is_none(), "Delegation before pipeline offset should be empty - \ @@ -212,13 +212,10 @@ mod tests { } // Check that bond is updated after the pipeline length for epoch in pos_params.pipeline_len..=pos_params.unbonding_len { - let start_epoch = - namada_tx_prelude::proof_of_stake::types::Epoch::from( - pos_params.pipeline_len, - ); + let start_epoch = Epoch::from(pos_params.pipeline_len); let expected_bond = HashMap::from_iter([(start_epoch, bond.amount)]); - let bond: Bond = bonds_post.get(epoch).unwrap(); + let bond: Bond = bonds_post.get(epoch).unwrap(); assert_eq!( bond.pos_deltas, expected_bond, "Delegation at and after pipeline offset should be equal \ @@ -229,12 +226,11 @@ mod tests { // This is a self-bond // Check that a bond already exists from genesis with initial stake // for the validator - let genesis_epoch = - namada_tx_prelude::proof_of_stake::types::Epoch::from(0); + let genesis_epoch = Epoch::from(0); for epoch in 0..pos_params.pipeline_len { let expected_bond = HashMap::from_iter([(genesis_epoch, initial_stake)]); - let bond: Bond = bonds_post + let bond: Bond = bonds_post .get(epoch) .expect("Genesis validator should already have self-bond"); assert_eq!( @@ -245,15 +241,12 @@ mod tests { } // Check that the bond is updated after the pipeline length for epoch in pos_params.pipeline_len..=pos_params.unbonding_len { - let start_epoch = - namada_tx_prelude::proof_of_stake::types::Epoch::from( - pos_params.pipeline_len, - ); + let start_epoch = Epoch::from(pos_params.pipeline_len); let expected_bond = HashMap::from_iter([ (genesis_epoch, initial_stake), (start_epoch, bond.amount), ]); - let bond: Bond = bonds_post.get(epoch).unwrap(); + let bond: Bond = bonds_post.get(epoch).unwrap(); assert_eq!( bond.pos_deltas, expected_bond, "Self-bond at and after pipeline offset should contain \ diff --git a/wasm/wasm_source/src/tx_unbond.rs b/wasm/wasm_source/src/tx_unbond.rs index dbc650d056..d7a6431243 100644 --- a/wasm/wasm_source/src/tx_unbond.rs +++ b/wasm/wasm_source/src/tx_unbond.rs @@ -250,7 +250,7 @@ mod tests { let unbonds_post = ctx().read_unbond(&unbond_id)?.unwrap(); let bonds_post = ctx().read_bond(&unbond_id)?.unwrap(); for epoch in 0..pos_params.unbonding_len { - let unbond: Option> = unbonds_post.get(epoch); + let unbond: Option = unbonds_post.get(epoch); assert!( unbond.is_none(), @@ -262,22 +262,18 @@ mod tests { let start_epoch = match &unbond.source { Some(_) => { // This bond was a delegation - namada_tx_prelude::proof_of_stake::types::Epoch::from( - pos_params.pipeline_len, - ) + Epoch::from(pos_params.pipeline_len) } None => { // This bond was a genesis validator self-bond - namada_tx_prelude::proof_of_stake::types::Epoch::default() + Epoch::default() } }; - let end_epoch = namada_tx_prelude::proof_of_stake::types::Epoch::from( - pos_params.unbonding_len - 1, - ); + let end_epoch = Epoch::from(pos_params.unbonding_len - 1); let expected_unbond = HashMap::from_iter([((start_epoch, end_epoch), unbond.amount)]); - let actual_unbond: Unbond = + let actual_unbond: Unbond = unbonds_post.get(pos_params.unbonding_len).unwrap(); assert_eq!( actual_unbond.deltas, expected_unbond, @@ -286,7 +282,7 @@ mod tests { ); for epoch in pos_params.pipeline_len..pos_params.unbonding_len { - let bond: Bond = bonds_post.get(epoch).unwrap(); + let bond: Bond = bonds_post.get(epoch).unwrap(); let expected_bond = HashMap::from_iter([(start_epoch, initial_stake)]); assert_eq!( @@ -297,7 +293,7 @@ mod tests { } { let epoch = pos_params.unbonding_len + 1; - let bond: Bond = bonds_post.get(epoch).unwrap(); + let bond: Bond = bonds_post.get(epoch).unwrap(); let expected_bond = HashMap::from_iter([(start_epoch, initial_stake)]); assert_eq!(