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 1 commit
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
Prev Previous commit
Next Next commit
Move offline inherents to consensus module.
Fixes #630
  • Loading branch information
gavofyork committed Aug 30, 2018
commit 5769344e4e7165bbd852555ac420ee9ca57b5b5c
3 changes: 2 additions & 1 deletion demo/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,9 @@ impl balances::Trait for Concrete {
pub type Balances = balances::Module<Concrete>;

impl consensus::Trait for Concrete {
const NOTE_OFFLINE_POSITION: u32 = 1;
type SessionKey = SessionKey;
type OnOfflineValidator = Staking;
}

/// Consensus module for this concrete runtime.
Expand Down Expand Up @@ -148,7 +150,6 @@ impl session::Trait for Concrete {
pub type Session = session::Module<Concrete>;

impl staking::Trait for Concrete {
const NOTE_MISSED_PROPOSAL_POSITION: u32 = 1;
type Event = Event;
}

Expand Down
9 changes: 1 addition & 8 deletions substrate/runtime/balances/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,14 @@ use primitives::traits::HasPublicAux;
use primitives::testing::{Digest, Header};
use substrate_primitives::{H256, KeccakHasher};
use runtime_io;
use {GenesisConfig, Module, Trait, consensus, system};
use {GenesisConfig, Module, Trait, system};

// Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted.
#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)]
pub struct Test;
impl HasPublicAux for Test {
type PublicAux = u64;
}
impl consensus::Trait for Test {
type SessionKey = u64;
}
impl system::Trait for Test {
type PublicAux = <Self as HasPublicAux>::PublicAux;
type Index = u64;
Expand All @@ -60,10 +57,6 @@ pub fn new_test_ext(ext_deposit: u64, monied: bool) -> runtime_io::TestExternali
} else {
1
};
t.extend(consensus::GenesisConfig::<Test>{
code: vec![],
authorities: vec![],
}.build_storage().unwrap());
t.extend(GenesisConfig::<Test>{
balances: if monied {
vec![(1, 10 * balance_factor), (2, 20 * balance_factor), (3, 30 * balance_factor), (4, 40 * balance_factor)]
Expand Down
35 changes: 33 additions & 2 deletions substrate/runtime/consensus/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ use rstd::prelude::*;
use runtime_support::{storage, Parameter};
use runtime_support::dispatch::Result;
use runtime_support::storage::unhashed::StorageVec;
use primitives::traits::MaybeSerializeDebug;
use primitives::traits::{MaybeSerializeDebug, MaybeEmpty};
use primitives::bft::MisbehaviorReport;

#[cfg(any(feature = "std", test))]
Expand All @@ -63,8 +63,20 @@ pub const CODE: &'static [u8] = b":code";

pub type KeyValue = (Vec<u8>, Vec<u8>);

pub trait OnOfflineValidator {
fn on_offline_validator(validator_index: usize);
}

impl OnOfflineValidator for () {
fn on_offline_validator(_validator_index: usize) {}
}

pub trait Trait: system::Trait {
/// The allowed extrinsic position for `note_offline` inherent.
const NOTE_OFFLINE_POSITION: u32;

type SessionKey: Parameter + Default + MaybeSerializeDebug;
type OnOfflineValidator: OnOfflineValidator;
}

decl_module! {
Expand All @@ -73,7 +85,8 @@ decl_module! {
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
pub enum Call where aux: T::PublicAux {
fn report_misbehavior(aux, report: MisbehaviorReport<T::Hash, T::BlockNumber>) -> Result = 0;
fn remark(aux, remark: Vec<u8>) -> Result = 1;
fn note_offline(aux, offline_val_indices: Vec<u32>) -> Result = 1;
fn remark(aux, remark: Vec<u8>) -> Result = 2;
}

#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
Expand Down Expand Up @@ -109,6 +122,24 @@ impl<T: Trait> Module<T> {
Ok(())
}

/// Note the previous block's validator missed their opportunity to propose a block. This only comes in
/// if 2/3+1 of the validators agree that no proposal was submitted. It's only relevant
/// for the previous block.
fn note_offline(aux: &T::PublicAux, offline_val_indices: Vec<u32>) -> Result {
assert!(aux.is_empty());
assert!(
<system::Module<T>>::extrinsic_index() == Some(T::NOTE_OFFLINE_POSITION),
"note_offline extrinsic must be at position {} in the block",
T::NOTE_OFFLINE_POSITION
);

for validator_index in offline_val_indices.into_iter() {
T::OnOfflineValidator::on_offline_validator(validator_index as usize);
}

Ok(())
}

/// Make some on-chain remark.
fn remark(_aux: &T::PublicAux, _remark: Vec<u8>) -> Result {
Ok(())
Expand Down
3 changes: 2 additions & 1 deletion substrate/runtime/executive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,9 @@ mod tests {
type PublicAux = u64;
}
impl consensus::Trait for Test {
const NOTE_OFFLINE_POSITION: u32 = 1;
type SessionKey = u64;
type OnOfflineValidator = staking::Module<Test>;
}
impl balances::Trait for Test {
type Balance = u64;
Expand All @@ -282,7 +284,6 @@ mod tests {
type Event = MetaEvent;
}
impl staking::Trait for Test {
const NOTE_MISSED_PROPOSAL_POSITION: u32 = 1;
type Event = MetaEvent;
}
impl timestamp::Trait for Test {
Expand Down
2 changes: 2 additions & 0 deletions substrate/runtime/session/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,9 @@ mod tests {
type PublicAux = u64;
}
impl consensus::Trait for Test {
const NOTE_OFFLINE_POSITION: u32 = 1;
type SessionKey = u64;
type OnOfflineValidator = ();
}
impl system::Trait for Test {
type PublicAux = <Self as HasPublicAux>::PublicAux;
Expand Down
90 changes: 37 additions & 53 deletions substrate/runtime/staking/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ use runtime_support::{Parameter, StorageValue, StorageMap};
use runtime_support::dispatch::Result;
use session::OnSessionChange;
use primitives::traits::{Zero, One, Bounded, RefInto, Executable,
As, AuxLookup, MaybeEmpty};
As, AuxLookup};
use balances::address::Address;

mod mock;
Expand Down Expand Up @@ -96,9 +96,6 @@ impl Default for SlashPreference {
}

pub trait Trait: balances::Trait + session::Trait {
/// The allowed extrinsic position for `missed_proposal` inherent.
const NOTE_MISSED_PROPOSAL_POSITION: u32;

/// The overarching event type.
type Event: From<Event<Self>> + Into<<Self as system::Trait>::Event>;
}
Expand All @@ -108,12 +105,11 @@ decl_module! {

#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
pub enum Call where aux: T::PublicAux {
fn note_missed_proposal(aux, offline_val_indices: Vec<u32>) -> Result = 0;
fn stake(aux) -> Result = 1;
fn unstake(aux, intentions_index: u32) -> Result = 2;
fn nominate(aux, target: Address<T::AccountId, T::AccountIndex>) -> Result = 3;
fn unnominate(aux, target_index: u32) -> Result = 4;
fn register_slash_preference(aux, intentions_index: u32, p: SlashPreference) -> Result = 5;
fn stake(aux) -> Result = 0;
fn unstake(aux, intentions_index: u32) -> Result = 1;
fn nominate(aux, target: Address<T::AccountId, T::AccountIndex>) -> Result = 2;
fn unnominate(aux, target_index: u32) -> Result = 3;
fn register_slash_preference(aux, intentions_index: u32, p: SlashPreference) -> Result = 4;
}

#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
Expand Down Expand Up @@ -321,49 +317,6 @@ impl<T: Trait> Module<T> {
Ok(())
}

/// Note the previous block's validator missed their opportunity to propose a block. This only comes in
/// if 2/3+1 of the validators agree that no proposal was submitted. It's only relevant
/// for the previous block.
fn note_missed_proposal(aux: &T::PublicAux, offline_val_indices: Vec<u32>) -> Result {
assert!(aux.is_empty());
assert!(
<system::Module<T>>::extrinsic_index() == Some(T::NOTE_MISSED_PROPOSAL_POSITION),
"note_missed_proposal extrinsic must be at position {} in the block",
T::NOTE_MISSED_PROPOSAL_POSITION
);

for validator_index in offline_val_indices.into_iter() {
let v = <session::Module<T>>::validators()[validator_index as usize].clone();
let slash_count = Self::slash_count(&v);
<SlashCount<T>>::insert(v.clone(), slash_count + 1);
let grace = Self::offline_slash_grace();

let event = if slash_count >= grace {
let instances = slash_count - grace;
let slash = Self::early_era_slash() << instances;
let next_slash = slash << 1u32;
let _ = Self::slash_validator(&v, slash);
if instances >= Self::slash_preference_of(&v).unstake_threshold
|| Self::slashable_balance(&v) < next_slash
{
if let Some(pos) = Self::intentions().into_iter().position(|x| &x == &v) {
Self::apply_unstake(&v, pos)
.expect("pos derived correctly from Self::intentions(); \
apply_unstake can only fail if pos wrong; \
Self::intentions() doesn't change; qed");
}
let _ = Self::force_new_era(false);
}
RawEvent::OfflineSlash(v, slash)
} else {
RawEvent::OfflineWarning(v, slash_count)
};
Self::deposit_event(event);
}

Ok(())
}

// PRIV DISPATCH

/// Deposit one of this module's events.
Expand Down Expand Up @@ -561,3 +514,34 @@ impl<T: Trait> balances::OnFreeBalanceZero<T::AccountId> for Module<T> {
<Bondage<T>>::remove(who);
}
}

impl<T: Trait> consensus::OnOfflineValidator for Module<T> {
fn on_offline_validator(validator_index: usize) {
let v = <session::Module<T>>::validators()[validator_index].clone();
let slash_count = Self::slash_count(&v);
<SlashCount<T>>::insert(v.clone(), slash_count + 1);
let grace = Self::offline_slash_grace();

let event = if slash_count >= grace {
let instances = slash_count - grace;
let slash = Self::early_era_slash() << instances;
let next_slash = slash << 1u32;
let _ = Self::slash_validator(&v, slash);
if instances >= Self::slash_preference_of(&v).unstake_threshold
|| Self::slashable_balance(&v) < next_slash
{
if let Some(pos) = Self::intentions().into_iter().position(|x| &x == &v) {
Self::apply_unstake(&v, pos)
.expect("pos derived correctly from Self::intentions(); \
apply_unstake can only fail if pos wrong; \
Self::intentions() doesn't change; qed");
}
let _ = Self::force_new_era(false);
}
RawEvent::OfflineSlash(v, slash)
} else {
RawEvent::OfflineWarning(v, slash_count)
};
Self::deposit_event(event);
}
}
3 changes: 2 additions & 1 deletion substrate/runtime/staking/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ impl HasPublicAux for Test {
type PublicAux = u64;
}
impl consensus::Trait for Test {
const NOTE_OFFLINE_POSITION: u32 = 1;
type SessionKey = u64;
type OnOfflineValidator = ();
}
impl system::Trait for Test {
type PublicAux = <Self as HasPublicAux>::PublicAux;
Expand Down Expand Up @@ -62,7 +64,6 @@ impl timestamp::Trait for Test {
type Moment = u64;
}
impl Trait for Test {
const NOTE_MISSED_PROPOSAL_POSITION: u32 = 1;
type Event = ();
}

Expand Down
Loading