mirror of
https://github.com/serai-dex/serai.git
synced 2025-12-08 20:29:23 +00:00
Add logic to amortize excess key shares, correcting is_bft
This commit is contained in:
@@ -187,9 +187,12 @@ pub mod pallet {
|
|||||||
fn is_bft(network: NetworkId) -> bool {
|
fn is_bft(network: NetworkId) -> bool {
|
||||||
let allocation_per_key_share = AllocationPerKeyShare::<T>::get(network).unwrap().0;
|
let allocation_per_key_share = AllocationPerKeyShare::<T>::get(network).unwrap().0;
|
||||||
|
|
||||||
|
let mut validators_len = 0;
|
||||||
let mut top = None;
|
let mut top = None;
|
||||||
let mut key_shares = 0;
|
let mut key_shares = 0;
|
||||||
for (_, amount) in SortedAllocationsIter::<T>::new(network) {
|
for (_, amount) in SortedAllocationsIter::<T>::new(network) {
|
||||||
|
validators_len += 1;
|
||||||
|
|
||||||
key_shares += amount.0 / allocation_per_key_share;
|
key_shares += amount.0 / allocation_per_key_share;
|
||||||
if top.is_none() {
|
if top.is_none() {
|
||||||
top = Some(key_shares);
|
top = Some(key_shares);
|
||||||
@@ -204,9 +207,10 @@ pub mod pallet {
|
|||||||
|
|
||||||
// key_shares may be over MAX_KEY_SHARES_PER_SET, which will cause an off-chain reduction of
|
// key_shares may be over MAX_KEY_SHARES_PER_SET, which will cause an off-chain reduction of
|
||||||
// each validator's key shares until their sum is MAX_KEY_SHARES_PER_SET
|
// each validator's key shares until their sum is MAX_KEY_SHARES_PER_SET
|
||||||
// That isn't modeled here, allowing an inaccuracy in an extreme edge case
|
// post_amortization_key_shares_for_top_validator yields what the top validator's key shares
|
||||||
// This may cause mis-reporting as BFT when not BFT (TODO: Investigate impact of this)
|
// would be after such a reduction, letting us evaluate this correctly
|
||||||
(top * 3) < key_shares
|
let top = post_amortization_key_shares_for_top_validator(validators_len, top, key_shares);
|
||||||
|
(top * 3) < key_shares.min(MAX_KEY_SHARES_PER_SET.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -92,3 +92,29 @@ pub fn musig_key(set: ValidatorSet, set_keys: &[Public]) -> Public {
|
|||||||
pub fn set_keys_message(set: &ValidatorSet, key_pair: &KeyPair) -> Vec<u8> {
|
pub fn set_keys_message(set: &ValidatorSet, key_pair: &KeyPair) -> Vec<u8> {
|
||||||
[b"ValidatorSets-key_pair".as_ref(), &(set, key_pair).encode()].concat()
|
[b"ValidatorSets-key_pair".as_ref(), &(set, key_pair).encode()].concat()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// For a set of validators whose key shares may exceed the maximum, reduce until they equal the
|
||||||
|
/// maximum.
|
||||||
|
///
|
||||||
|
/// Reduction occurs by reducing each validator in a reverse round-robin.
|
||||||
|
pub fn amortize_excess_key_shares(validators: &mut [(Public, u64)]) {
|
||||||
|
let total_key_shares = validators.iter().map(|(_, shares)| shares).sum::<u64>();
|
||||||
|
for i in
|
||||||
|
0 .. usize::try_from(total_key_shares.saturating_sub(MAX_KEY_SHARES_PER_SET.into())).unwrap()
|
||||||
|
{
|
||||||
|
validators[validators.len() - ((i % validators.len()) + 1)].1 -= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the post-amortization key shares for the top validator.
|
||||||
|
///
|
||||||
|
/// Panics when `validators == 0`.
|
||||||
|
pub fn post_amortization_key_shares_for_top_validator(
|
||||||
|
validators: usize,
|
||||||
|
top: u64,
|
||||||
|
key_shares: u64,
|
||||||
|
) -> u64 {
|
||||||
|
top -
|
||||||
|
(key_shares.saturating_sub(MAX_KEY_SHARES_PER_SET.into()) /
|
||||||
|
u64::try_from(validators).unwrap())
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user