Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file not shown.
Binary file not shown.
2 changes: 1 addition & 1 deletion polkadot/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
spec_name: ver_str!("polkadot"),
impl_name: ver_str!("parity-polkadot"),
authoring_version: 1,
spec_version: 2,
spec_version: 100,
impl_version: 0,
};

Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
60 changes: 53 additions & 7 deletions substrate/runtime/session/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ decl_module! {
fn force_new_session(normal_rotation: bool) -> Result = 1;
}
}

decl_storage! {
trait Store for Module<T: Trait>;

Expand All @@ -93,6 +94,9 @@ decl_storage! {
// Percent by which the session must necessarily finish late before we early-exit the session.
pub BrokenPercentLate get(broken_percent_late): b"ses:broken_percent_late" => required T::Moment;

// New session is being forced is this entry exists; in which case, the boolean value is whether
// the new session should be considered a normal rotation (rewardable) or exceptional (slashable).
pub ForcingNewSession get(forcing_new_session): b"ses:forcing_new_session" => bool;
// Block at which the session length last changed.
LastLengthChange: b"ses:llc" => T::BlockNumber;
// The next key for a given validator.
Expand Down Expand Up @@ -127,8 +131,8 @@ impl<T: Trait> Module<T> {
}

/// Forces a new session.
fn force_new_session(normal_rotation: bool) -> Result {
Self::rotate_session(normal_rotation);
pub fn force_new_session(normal_rotation: bool) -> Result {
<ForcingNewSession<T>>::put(normal_rotation);
Ok(())
}

Expand All @@ -153,13 +157,16 @@ impl<T: Trait> Module<T> {
let block_number = <system::Module<T>>::block_number();
let is_final_block = ((block_number - Self::last_length_change()) % Self::length()).is_zero();
let broken_validation = Self::broken_validation();
if is_final_block || broken_validation {
Self::rotate_session(!broken_validation);
if let Some(normal_rotation) = Self::forcing_new_session() {
Self::rotate_session(normal_rotation, is_final_block);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure about how force_new_session() will be used, but probably Self::rotate_session(normal_rotation && !broken_validation, is_final_block) would be better (to make sure we slash validators)?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the idea is that if you use force_new_session(), then it is able to override everything else in terms of the slashing.

if force_new_session() isn't the reason that this session is ending, then slashing is done if this session has been prematurely ended.

<ForcingNewSession<T>>::kill();
} else if is_final_block || broken_validation {
Self::rotate_session(!broken_validation, is_final_block);
}
}

/// Move onto next session: register the new authority set.
pub fn rotate_session(normal_rotation: bool) {
pub fn rotate_session(normal_rotation: bool, is_final_block: bool) {
let now = <timestamp::Module<T>>::get();
let time_elapsed = now.clone() - Self::current_start();

Expand All @@ -168,9 +175,14 @@ impl<T: Trait> Module<T> {
<CurrentStart<T>>::put(now);

// Enact era length change.
if let Some(next_len) = <NextSessionLength<T>>::take() {
let block_number = <system::Module<T>>::block_number();
let len_changed = if let Some(next_len) = <NextSessionLength<T>>::take() {
<SessionLength<T>>::put(next_len);
true
} else {
false
};
if len_changed || !is_final_block {
let block_number = <system::Module<T>>::block_number();
<LastLengthChange<T>>::put(block_number);
}

Expand Down Expand Up @@ -354,6 +366,40 @@ mod tests {
});
}

#[test]
fn should_work_with_early_exit() {
with_externalities(&mut new_test_ext(), || {
System::set_block_number(1);
assert_ok!(Session::set_length(10));
assert_eq!(Session::blocks_remaining(), 1);
Session::check_rotate_session();

System::set_block_number(2);
assert_eq!(Session::blocks_remaining(), 0);
Session::check_rotate_session();
assert_eq!(Session::length(), 10);

System::set_block_number(7);
assert_eq!(Session::current_index(), 1);
assert_eq!(Session::blocks_remaining(), 5);
assert_ok!(Session::force_new_session(false));
Session::check_rotate_session();

System::set_block_number(8);
assert_eq!(Session::current_index(), 2);
assert_eq!(Session::blocks_remaining(), 9);
Session::check_rotate_session();

System::set_block_number(17);
assert_eq!(Session::current_index(), 2);
assert_eq!(Session::blocks_remaining(), 0);
Session::check_rotate_session();

System::set_block_number(18);
assert_eq!(Session::current_index(), 3);
});
}

#[test]
fn session_length_change_should_work() {
with_externalities(&mut new_test_ext(), || {
Expand Down
19 changes: 13 additions & 6 deletions substrate/runtime/staking/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ decl_module! {
fn set_sessions_per_era(new: T::BlockNumber) -> Result = 0;
fn set_bonding_duration(new: T::BlockNumber) -> Result = 1;
fn set_validator_count(new: u32) -> Result = 2;
fn force_new_era() -> Result = 3;
fn force_new_era(should_slash: bool) -> Result = 3;
}
}

Expand Down Expand Up @@ -182,6 +182,9 @@ decl_storage! {
// The enumeration sets.
pub EnumSet get(enum_set): b"sta:enum_set" => default map [ T::AccountIndex => Vec<T::AccountId> ];

// We are forcing a new era.
pub ForcingNewEra get(forcing_new_era): b"sta:forcing_new_era" => ();

// The "free" balance of a given account.
//
// This is the only balance that matters in terms of most operations on tokens. It is
Expand Down Expand Up @@ -403,10 +406,11 @@ impl<T: Trait> Module<T> {
Ok(())
}

/// Force there to be a new era. This also forces a new session immediately after.
fn force_new_era() -> Result {
<session::Module<T>>::rotate_session(false);
Ok(())
/// Force there to be a new era. This also forces a new session immediately after by
/// setting `normal_rotation` to be false. Validators will get slashed.
fn force_new_era(should_slash: bool) -> Result {
<ForcingNewEra<T>>::put(());
<session::Module<T>>::force_new_session(!should_slash)
}

// PUBLIC MUTABLES (DANGEROUS)
Expand Down Expand Up @@ -621,7 +625,10 @@ impl<T: Trait> Module<T> {
}
}
}
if ((session_index - Self::last_era_length_change()) % Self::sessions_per_era()).is_zero() || !normal_rotation {
if <ForcingNewEra<T>>::take().is_some()
|| ((session_index - Self::last_era_length_change()) % Self::sessions_per_era()).is_zero()
|| !normal_rotation
{
Self::new_era();
}
}
Expand Down
Binary file not shown.
Binary file not shown.