diff --git a/coordinator/src/substrate/mod.rs b/coordinator/src/substrate/mod.rs index 7a76353c..fb1e3aed 100644 --- a/coordinator/src/substrate/mod.rs +++ b/coordinator/src/substrate/mod.rs @@ -11,10 +11,7 @@ use ciphersuite::{group::GroupEncoding, Ciphersuite, Ristretto}; use serai_client::{ SeraiError, Block, Serai, TemporalSerai, primitives::{BlockHash, NetworkId}, - validator_sets::{ - primitives::{ValidatorSet, amortize_excess_key_shares}, - ValidatorSetsEvent, - }, + validator_sets::{primitives::ValidatorSet, ValidatorSetsEvent}, in_instructions::InInstructionsEvent, coins::CoinsEvent, }; @@ -69,12 +66,7 @@ async fn handle_new_set( let set_participants = serai.participants(set.network).await?.expect("NewSet for set which doesn't exist"); - let mut set_data = set_participants - .into_iter() - .map(|(k, w)| (k, u16::try_from(w).unwrap())) - .collect::>(); - amortize_excess_key_shares(&mut set_data); - set_data + set_participants.into_iter().map(|(k, w)| (k, u16::try_from(w).unwrap())).collect::>() }; let time = if let Ok(time) = block.time() { diff --git a/substrate/validator-sets/pallet/src/lib.rs b/substrate/validator-sets/pallet/src/lib.rs index 76c07e1c..d1385c2d 100644 --- a/substrate/validator-sets/pallet/src/lib.rs +++ b/substrate/validator-sets/pallet/src/lib.rs @@ -363,21 +363,26 @@ pub mod pallet { let allocation_per_key_share = Self::allocation_per_key_share(network).unwrap().0; - let mut iter = SortedAllocationsIter::::new(network); let mut participants = vec![]; - let mut key_shares = 0; let mut total_stake = 0; - while key_shares < u64::from(MAX_KEY_SHARES_PER_SET) { - let Some((key, amount)) = iter.next() else { break }; + { + let mut iter = SortedAllocationsIter::::new(network); + let mut key_shares = 0; + while key_shares < u64::from(MAX_KEY_SHARES_PER_SET) { + let Some((key, amount)) = iter.next() else { break }; - let these_key_shares = amount.0 / allocation_per_key_share; - InSet::::set(network, key, Some(these_key_shares)); - participants.push((key, these_key_shares)); + let these_key_shares = + (amount.0 / allocation_per_key_share).min(u64::from(MAX_KEY_SHARES_PER_SET)); + participants.push((key, these_key_shares)); - // This can technically set key_shares to a value exceeding MAX_KEY_SHARES_PER_SET - // Off-chain, the key shares per validator will be accordingly adjusted - key_shares += these_key_shares; - total_stake += amount.0; + key_shares += these_key_shares; + total_stake += amount.0; + } + amortize_excess_key_shares(&mut participants); + } + + for (key, shares) in &participants { + InSet::::set(network, key, Some(*shares)); } TotalAllocatedStake::::set(network, Some(Amount(total_stake))); diff --git a/substrate/validator-sets/primitives/src/lib.rs b/substrate/validator-sets/primitives/src/lib.rs index 644b19e1..c900b0a9 100644 --- a/substrate/validator-sets/primitives/src/lib.rs +++ b/substrate/validator-sets/primitives/src/lib.rs @@ -115,11 +115,11 @@ pub fn report_slashes_message(set: &ValidatorSet, slashes: &[(Public, u32)]) -> /// maximum. /// /// Reduction occurs by reducing each validator in a reverse round-robin. -pub fn amortize_excess_key_shares(validators: &mut [(Public, u16)]) { - let total_key_shares = validators.iter().map(|(_, shares)| shares).sum::(); - for i in 0 .. usize::from( - total_key_shares.saturating_sub(u16::try_from(MAX_KEY_SHARES_PER_SET).unwrap()), - ) { +pub fn amortize_excess_key_shares(validators: &mut [(Public, u64)]) { + let total_key_shares = validators.iter().map(|(_, shares)| shares).sum::(); + for i in 0 .. usize::try_from(total_key_shares.saturating_sub(u64::from(MAX_KEY_SHARES_PER_SET))) + .unwrap() + { validators[validators.len() - ((i % validators.len()) + 1)].1 -= 1; } }