Skip to content

Commit

Permalink
HOTFIX: Generate thea auth change message before era ends. (#849)
Browse files Browse the repository at this point in the history
## Describe your changes
Thea should generate the validator session change message at the
beginning of the last epoch of an era and get the changes to effect at
the end.

## Checklist before requesting a review
- [x] I have performed a self-review of my code.
- [ ] If it is a core feature, I have added thorough tests.
- [x] I removed all Clippy and Formatting Warnings. 
- [ ] I added required Copyrights.
  • Loading branch information
Gauthamastro authored Jul 27, 2023
2 parents c6c1572 + 448826b commit 5f39dc2
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 36 deletions.
14 changes: 7 additions & 7 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

31 changes: 20 additions & 11 deletions pallets/thea/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ use sp_runtime::{
Percent, RuntimeAppPublic, SaturatedConversion,
};
use sp_std::prelude::*;
use thea_primitives::{types::Message, Network, GENESIS_AUTHORITY_SET_ID};
use thea_primitives::{types::Message, Network, ValidatorSet, GENESIS_AUTHORITY_SET_ID};

#[cfg(feature = "runtime-benchmarks")]
mod benchmarking;
Expand Down Expand Up @@ -358,28 +358,37 @@ impl<T: Config> Pallet<T> {
}

fn change_authorities(
incoming: BoundedVec<T::TheaId, T::MaxAuthorities>,
queued: BoundedVec<T::TheaId, T::MaxAuthorities>,
incoming: BoundedVec<T::TheaId, T::MaxAuthorities>, // n+1th set
queued: BoundedVec<T::TheaId, T::MaxAuthorities>, // n+ 2th set
) {
// ( outgoing) -> (validators/incoming) -> (queued)
// nth epoch -> n+1th epoch -> n+2nd epoch
let id = Self::validator_set_id();
let outgoing = <Authorities<T>>::get(id);
let outgoing = <Authorities<T>>::get(id); // nth set ( active ,current )
let new_id = id + 1u64;

// We need to issue a new message if the validator set is changing,
// that is, the incoming set is has different session keys from outgoing set.
// This last message should be signed by the outgoing set
// Similar to how Grandpa's session change works.
if outgoing != incoming {
if incoming != queued {
// This should happen at the beginning of the last epoch
let active_networks = <ActiveNetworks<T>>::get();
for network in active_networks {
let message = Self::generate_payload(true, network, incoming.encode());
// Update nonce
<OutgoingNonce<T>>::insert(message.network, message.nonce);
<OutgoingMessages<T>>::insert(message.network, message.nonce, message);
if let Some(validator_set) = ValidatorSet::new(queued.clone(), new_id) {
let payload = validator_set.encode();
for network in active_networks {
let message = Self::generate_payload(true, network, payload.clone());
// Update nonce
<OutgoingNonce<T>>::insert(message.network, message.nonce);
<OutgoingMessages<T>>::insert(message.network, message.nonce, message);
}
}
<NextAuthorities<T>>::put(queued);
}
if incoming != outgoing {
// This will happen when new era starts, or end of the last epoch
<Authorities<T>>::insert(new_id, incoming);
<ValidatorSetId<T>>::put(new_id);
<NextAuthorities<T>>::put(queued);
}
}

Expand Down
57 changes: 40 additions & 17 deletions pallets/thea/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,32 +65,55 @@ use frame_support::traits::OneSessionHandler;
#[test]
fn test_session_change() {
new_test_ext().execute_with(|| {
let mut validators = Vec::with_capacity(200);
for i in 0..200 {
validators.push(
Pair::generate_with_phrase(Some(format!("{}//{}", WELL_KNOWN, i).as_str())).0,
);
let mut authorities: Vec<(&u64, <Test as Config>::TheaId)> = Vec::with_capacity(200);
for i in 0..200u64 {
authorities.push((
&1,
Pair::generate_with_phrase(Some(format!("{}//{}", WELL_KNOWN, i).as_str()))
.0
.public()
.into(),
));
}

let mut queued: Vec<(&u64, <Test as Config>::TheaId)> = Vec::with_capacity(200);
for i in 0..200u64 {
queued.push((
&1,
Pair::generate_with_phrase(Some(format!("{}//{}", WELL_KNOWN, i).as_str()))
.0
.public()
.into(),
));
}

let mut authorities = Vec::new();
validators
.clone()
.into_iter()
.for_each(|bls| authorities.push((&1, bls.public().into())));
let mut networks = BTreeSet::new();
networks.insert(1);
<ActiveNetworks<Test>>::put(networks);
assert!(Thea::validator_set_id() == 0);
assert!(Thea::outgoing_nonce(1) == 0);
let authorities_cloned: Vec<(&u64, <Test as Config>::TheaId)> = authorities.clone();
let auth_len = authorities_cloned.len();
Thea::on_new_session(false, authorities.into_iter(), authorities_cloned.into_iter());
let current_authorities: Vec<<Test as Config>::TheaId> =
authorities.iter().map(|(_, public)| public.clone()).collect();
<ValidatorSetId<Test>>::put(0);
<Authorities<Test>>::insert(0, BoundedVec::truncate_from(current_authorities));
// Simulating the on_new_session to last epoch of an era.
Thea::on_new_session(false, authorities.into_iter(), queued.clone().into_iter());
assert!(Thea::validator_set_id() == 0);
assert!(Thea::outgoing_nonce(1) == 1); // Thea validator session change message is generated here

let message = Thea::get_outgoing_messages(1, 1).unwrap();
assert_eq!(message.nonce, 1);
let validator_set: ValidatorSet<<Test as Config>::TheaId> =
ValidatorSet::decode(&mut &message.data[..]).unwrap();
let queued_validators: Vec<<Test as Config>::TheaId> =
queued.iter().map(|(_, public)| public.clone()).collect();
assert_eq!(validator_set.set_id, 1);
assert_eq!(validator_set.validators, queued_validators);

// Simulating the on_new_session to the first epoch of the next era.
Thea::on_new_session(false, queued.clone().into_iter(), queued.clone().into_iter());
assert!(Thea::validator_set_id() == 1);
assert!(Thea::outgoing_nonce(1) == 1);
let message = Thea::get_outgoing_messages(1, 1).unwrap();
let bounded_vec: BoundedVec<<Test as Config>::TheaId, <Test as Config>::MaxAuthorities> =
BoundedVec::decode(&mut &message.data[..]).unwrap();
assert_eq!(bounded_vec.to_vec().len(), auth_len);
})
}

Expand Down
2 changes: 1 addition & 1 deletion runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
// and set impl_version to 0. If only runtime
// implementation changes and behavior does not, then leave spec_version as
// is and increment impl_version.
spec_version: 289,
spec_version: 292,
impl_version: 0,
apis: RUNTIME_API_VERSIONS,
transaction_version: 2,
Expand Down

0 comments on commit 5f39dc2

Please sign in to comment.