Skip to content

Commit

Permalink
add signer roation
Browse files Browse the repository at this point in the history
  • Loading branch information
JesseAbram committed Jul 16, 2024
1 parent d464a99 commit 354fa14
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 11 deletions.
34 changes: 25 additions & 9 deletions pallets/staking/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,7 @@ pub mod pallet {
.or(Err(Error::<T>::InvalidValidatorId))?;

pallet_staking::Pallet::<T>::withdraw_unbonded(origin, num_slashing_spans)?;

// TODO: do not allow unbonding of validator if not enough validators
if pallet_staking::Pallet::<T>::bonded(&controller).is_none() {
let server_info =
ThresholdServers::<T>::take(&validator_id).ok_or(Error::<T>::NoThresholdKey)?;
Expand Down Expand Up @@ -402,26 +402,42 @@ pub mod pallet {
Ok(ledger.stash)
}

pub fn get_randomness() -> u32 {
pub fn get_randomness() -> ChaCha20Rng {
let phrase = b"signer_rotation";
// TODO: Is randomness freshness an issue here
// https://github.com/paritytech/substrate/issues/8312
let (seed, _) = T::Randomness::random(phrase);
// seed needs to be guaranteed to be 32 bytes.
let seed = <[u8; 32]>::decode(&mut TrailingZeroInput::new(seed.as_ref()))
.expect("input is padded with zeroes; qed");
let mut rng = ChaChaRng::from_seed(seed);
rng.next_u32()
ChaChaRng::from_seed(seed)
}

pub fn new_session_handler(
validators: &[<T as pallet_session::Config>::ValidatorId],
) -> Result<(), DispatchError> {
let phrase = b"signer_rotation";
let randomness = Self::get_randomness();
let index = randomness % validators.len() as u32;
let next_signer_up = &validators[index as usize];
// check to make sure signer selected does not exist in signer selection already
let mut current_signers = Self::signers();
// Since not enough validators do not allow rotation
// TODO: open issue to discuss
if validators.len() <= current_signers.len() {
return Ok(());
}
let mut randomness = Self::get_randomness();
// grab a current signer to initiate value
let mut next_signer_up = &current_signers[0].clone();
let mut index;
// loops to find signer in validator that is not already signer
while current_signers.contains(&next_signer_up) {
index = randomness.next_u32() % validators.len() as u32;
next_signer_up = &validators[index as usize];
}

// removes first signer and pushes new signer to back
current_signers.remove(0);
current_signers.push(next_signer_up.clone());
NextSigners::<T>::put(current_signers);

// for next PR
// tell signers to do new key rotation with new signer group (dkg)
// confirm action has taken place

Expand Down
21 changes: 19 additions & 2 deletions pallets/staking/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,23 @@ fn it_declares_synced() {
}

#[test]
fn it_tests_randomness() {
new_test_ext().execute_with(|| Staking::get_randomness());
fn it_tests_new_session_handler() {
new_test_ext().execute_with(|| {
// start with current validators as 6 and 5

// no next signers at start
assert_eq!(Staking::next_signers().len(), 0);

Staking::new_session_handler(&vec![1u64, 2u64, 3u64]);
// takes signers original (5,6) pops off first 5, adds (fake randomness in mock so adds 1)
assert_eq!(Staking::next_signers(), vec![6u64, 1u64]);

Staking::new_session_handler(&vec![6u64, 5u64, 3u64]);
// takes 3 and leaves 5 and 6 since already in signer group
assert_eq!(Staking::next_signers(), vec![6u64, 3u64]);

Staking::new_session_handler(&vec![1u64]);
// does nothing as not enough validators
assert_eq!(Staking::next_signers(), vec![6u64, 3u64]);
});
}

0 comments on commit 354fa14

Please sign in to comment.