Skip to content

Commit

Permalink
feat(data_structures): order validators by stake when sampling superb…
Browse files Browse the repository at this point in the history
…lock commitees
  • Loading branch information
aesedepece committed Dec 26, 2024
1 parent 0ebb227 commit a9ae6e6
Show file tree
Hide file tree
Showing 4 changed files with 19 additions and 21 deletions.
16 changes: 0 additions & 16 deletions data_structures/src/staking/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -287,22 +287,6 @@ pub struct CoinsAndAddresses<Coins, Address> {
pub addresses: StakeKey<Address>,
}

/// Allows telling the `census` method in `Stakes` to source addresses from its internal `by_coins`
/// following different strategies.
#[repr(u8)]
#[derive(Clone, Copy, Debug)]
pub enum CensusStrategy {
/// Retrieve all addresses, ordered by decreasing power.
All = 0,
/// Retrieve every Nth address, ordered by decreasing power.
StepBy(usize) = 1,
/// Retrieve the most powerful N addresses, ordered by decreasing power.
Take(usize) = 2,
/// Retrieve a total of N addresses, evenly distributed from the index, ordered by decreasing
/// power.
Evenly(usize) = 3,
}

impl<const UNIT: u8, Address, Coins, Epoch, Nonce, Power> Serialize
for Stakes<UNIT, Address, Coins, Epoch, Nonce, Power>
where
Expand Down
14 changes: 14 additions & 0 deletions data_structures/src/staking/stakes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,20 @@ where
self.by_validator.len()
}

/// Retrieve all validators, ordered by the total amount of stake that they operate.
pub fn validators_by_stake(&self) -> impl Iterator<Item = (Address, Coins)> + Clone + '_ {
self.by_validator
.iter()
.map(|(address, entries)| {
let coins = entries.iter().fold(Coins::zero(), |acc, entry| {
acc + entry.value.read().unwrap().coins
});

(address.clone(), coins)
})
.sorted_by_key(|(_, coins)| *coins)
}

/// Tells what is the power of an identity in the network on a certain epoch.
pub fn query_power<ISK>(
&self,
Expand Down
2 changes: 1 addition & 1 deletion data_structures/src/superblock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ pub enum SuperBlockConsensus {
///
/// Different protocol versions populate this data differently:
/// - In V1_X, this contained a complete list of all ARS identities.
/// - In V2_X, it is expected to contain all validators instead.
/// - In V2_X, it is expected to contain a list of validators instead.
#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)]
pub struct Census {
// HashSet containing the identities
Expand Down
8 changes: 4 additions & 4 deletions node/src/actors/chain_manager/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2043,17 +2043,17 @@ impl ChainManager {
// - In V1_X protocols, the census was sourced from the ARS. Namely, it contains
// all identities with non-zero reputation, ordered by decreasing reputation.
// - In V2_x protocols, the census is instead sourced from the stakes tracker.
// Namely, it contains the two top quartiles of the most powerful validators,
// ordered by power.
// Namely, it contains the two top quartiles of the validators that operate the
// most stake.
// Exceptionally, if a base census has been constructed above, all of this logic is
// skipped, and the base census is used.
let census = Census::new(base_census.unwrap_or(
if ProtocolVersion::from_epoch(block_epoch) < ProtocolVersion::V2_0 {
reputation_engine.get_rep_ordered_ars_list()
} else {
let all_validators = act.chain_state.stakes.by_rank(Capability::Mining, block_epoch);
let all_validators = act.chain_state.stakes.validators_by_stake();
let half_count = act.chain_state.stakes.validators_count() / 2;
let top_validators = all_validators.map(|(StakeKey { validator, .. }, _)| validator).take(half_count).collect();
let top_validators = all_validators.map(|(validator, _)| validator).take(half_count).collect();

top_validators
}));
Expand Down

0 comments on commit a9ae6e6

Please sign in to comment.