Browse Source

substrate v2: add staking and some fixes

Mokhtar Naamani 5 years ago
parent
commit
f34568f907
6 changed files with 225 additions and 35 deletions
  1. 72 3
      Cargo.toml
  2. 1 1
      src/governance/council.rs
  3. 3 1
      src/governance/election.rs
  4. 14 20
      src/governance/proposals.rs
  5. 129 6
      src/lib.rs
  6. 6 4
      src/service_discovery/discovery.rs

+ 72 - 3
Cargo.toml

@@ -8,6 +8,15 @@ version = '6.0.0'
 default = ['std']
 no_std = []
 std = [
+    'authority-discovery-primitives/std',
+    'authority-discovery/std',
+    'authorship/std',
+    'finality-tracker/std',
+    'im-online/std',
+    'session/std',
+    'offences/std',
+    'sr-staking-primitives/std',
+    'staking/std',
     'codec/std',
     'substrate-client/std',
     'rstd/std',
@@ -30,6 +39,7 @@ std = [
     'offchain-primitives/std',
     'substrate-session/std',
     'forum/std',
+    'node-primitives/std'
 ]
 
 [dependencies.babe]
@@ -113,7 +123,6 @@ features = ['derive']
 optional = true
 version = '1.0'
 
-#renamed from runtime_primitives
 [dependencies.runtime-primitives]
 default_features = false
 git = 'https://github.com/paritytech/substrate.git'
@@ -155,6 +164,66 @@ git = 'https://github.com/paritytech/substrate.git'
 package = 'sr-version'
 branch = 'master'
 
+[dependencies.authority-discovery-primitives]
+default_features = false
+git = 'https://github.com/paritytech/substrate.git'
+package = 'substrate-authority-discovery-primitives'
+branch = 'master'
+
+[dependencies.authority-discovery]
+default_features = false
+git = 'https://github.com/paritytech/substrate.git'
+package = 'srml-authority-discovery'
+branch = 'master'
+
+[dependencies.authorship]
+default_features = false
+git = 'https://github.com/paritytech/substrate.git'
+package = 'srml-authorship'
+branch = 'master'
+
+[dependencies.finality-tracker]
+default_features = false
+git = 'https://github.com/paritytech/substrate.git'
+package = 'srml-finality-tracker'
+branch = 'master'
+
+[dependencies.im-online]
+default_features = false
+git = 'https://github.com/paritytech/substrate.git'
+package = 'srml-im-online'
+branch = 'master'
+
+[dependencies.session]
+default_features = false
+git = 'https://github.com/paritytech/substrate.git'
+package = 'srml-session'
+branch = 'master'
+
+[dependencies.offences]
+default_features = false
+git = 'https://github.com/paritytech/substrate.git'
+package = 'srml-offences'
+branch = 'master'
+
+[dependencies.sr-staking-primitives]
+default_features = false
+git = 'https://github.com/paritytech/substrate.git'
+package = 'sr-staking-primitives'
+branch = 'master'
+
+[dependencies.staking]
+default_features = false
+git = 'https://github.com/paritytech/substrate.git'
+package = 'srml-staking'
+branch = 'master'
+
+[dependencies.node-primitives]
+default_features = false
+git = 'https://github.com/paritytech/substrate.git'
+package = 'node-primitives'
+branch = 'master'
+
 [build-dependencies.wasm-builder-runner]
 package = 'substrate-wasm-builder-runner'
 version = '1.0.2'
@@ -163,6 +232,6 @@ version = '1.0.2'
 default_features = false
 git = 'https://github.com/mnaamani/substrate-forum-module'
 package = 'substrate-forum-module'
-branch = "substrate-v2"
+branch = 'substrate-v2'
 # Before releasing Rome - finalize and tag release new forum and update this
-# tag = "v1.0.0"
+# tag = 'v1.0.0'

+ 1 - 1
src/governance/council.rs

@@ -30,7 +30,7 @@ pub trait Trait: system::Trait + GovernanceCurrency {
 decl_storage! {
     trait Store for Module<T: Trait> as Council {
         ActiveCouncil get(active_council) config(): Seats<T::AccountId, BalanceOf<T>>;
-        TermEndsAt get(term_ends_at) config() : T::BlockNumber = T::BlockNumber::one();
+        TermEndsAt get(term_ends_at) config() : T::BlockNumber = T::BlockNumber::from(1);
     }
 }
 

+ 3 - 1
src/governance/election.rs

@@ -9,6 +9,8 @@ use codec::{Decode, Encode};
 use rstd::collections::btree_map::BTreeMap;
 use rstd::ops::Add;
 use runtime_primitives::traits::{Hash, Zero};
+#[cfg(feature = "std")]
+use serde::{Deserialize, Serialize};
 
 use super::sealed_vote::SealedVote;
 use super::stake::Stake;
@@ -206,7 +208,7 @@ impl<T: Trait> Module<T> {
     /// for entering the stage has been performed.
     /// Bumps the election round.
     fn move_to_announcing_stage() {
-        let next_round = <Round<T>>::mutate(|n| {
+        let next_round = Round::mutate(|n| {
             *n += 1;
             *n
         });

+ 14 - 20
src/governance/proposals.rs

@@ -1,15 +1,15 @@
 use codec::{Decode, Encode};
 use rstd::prelude::*;
 use runtime_io::print;
-use runtime_primitives::traits::{Hash, Zero};
-use srml_support::traits::{Currency, ReservableCurrency};
+use runtime_primitives::traits::{Hash, SaturatedConversion, Zero};
+#[cfg(feature = "std")]
+use serde::{Deserialize, Serialize};
+use srml_support::traits::{Currency, Get, ReservableCurrency};
 use srml_support::{
     decl_event, decl_module, decl_storage, dispatch, ensure, StorageMap, StorageValue,
 };
-use {
-    consensus,
-    system::{self, ensure_root, ensure_signed},
-};
+
+use system::{self, ensure_root, ensure_signed};
 
 #[cfg(test)]
 use primitives::storage::well_known_keys;
@@ -19,12 +19,12 @@ pub use crate::currency::{BalanceOf, GovernanceCurrency};
 use crate::traits::Members;
 
 const DEFAULT_APPROVAL_QUORUM: u32 = 60;
-const DEFAULT_MIN_STAKE: u64 = 100;
-const DEFAULT_CANCELLATION_FEE: u64 = 5;
-const DEFAULT_REJECTION_FEE: u64 = 10;
+const DEFAULT_MIN_STAKE: u32 = 100;
+const DEFAULT_CANCELLATION_FEE: u32 = 5;
+const DEFAULT_REJECTION_FEE: u32 = 10;
 
-const DEFAULT_VOTING_PERIOD_IN_DAYS: u64 = 10;
-const DEFAULT_VOTING_PERIOD_IN_SECS: u64 = DEFAULT_VOTING_PERIOD_IN_DAYS * 24 * 60 * 60;
+const DEFAULT_VOTING_PERIOD_IN_DAYS: u32 = 10;
+const DEFAULT_VOTING_PERIOD_IN_SECS: u32 = DEFAULT_VOTING_PERIOD_IN_DAYS * 24 * 60 * 60;
 
 const DEFAULT_NAME_MAX_LEN: u32 = 100;
 const DEFAULT_DESCRIPTION_MAX_LEN: u32 = 10_000;
@@ -121,7 +121,7 @@ pub struct TallyResult<BlockNumber> {
     finalized_at: BlockNumber,
 }
 
-pub trait Trait: timestamp::Trait + council::Trait + consensus::Trait + GovernanceCurrency {
+pub trait Trait: timestamp::Trait + council::Trait + GovernanceCurrency {
     /// The overarching event type.
     type Event: From<Event<Self>> + Into<<Self as system::Trait>::Event>;
 
@@ -185,7 +185,7 @@ decl_storage! {
         /// Max duration of proposal in blocks until it will be expired if not enough votes.
         VotingPeriod get(voting_period) config(): T::BlockNumber =
             T::BlockNumber::from(DEFAULT_VOTING_PERIOD_IN_SECS /
-            (<timestamp::Module<T>>::minimum_period().as_() * 2));
+            (<T as timestamp::Trait>::MinimumPeriod::get().saturated_into::<u32>() * 2));
 
         NameMaxLen get(name_max_len) config(): u32 = DEFAULT_NAME_MAX_LEN;
         DescriptionMaxLen get(description_max_len) config(): u32 = DEFAULT_DESCRIPTION_MAX_LEN;
@@ -543,7 +543,7 @@ impl<T: Trait> Module<T> {
         let _ = T::Currency::unreserve(&proposal.proposer, proposal.stake);
 
         // Update wasm code of node's runtime:
-        <consensus::Module<T>>::set_code(wasm_code)?;
+        <system::Module<T>>::set_code(wasm_code)?;
 
         Self::deposit_event(RawEvent::RuntimeUpdated(proposal_id, proposal.wasm_hash));
 
@@ -576,12 +576,6 @@ mod tests {
     #[derive(Clone, Eq, PartialEq)]
     pub struct Test;
 
-    impl consensus::Trait for Test {
-        type SessionKey = UintAuthorityId;
-        type InherentOfflineReport = ();
-        type Log = DigestItem;
-    }
-
     impl system::Trait for Test {
         type Origin = Origin;
         type Index = u64;

+ 129 - 6
src/lib.rs

@@ -11,6 +11,7 @@ include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));
 use babe::AuthorityId as BabeId;
 use grandpa::fg_primitives::{self, ScheduledChange};
 use grandpa::{AuthorityId as GrandpaId, AuthorityWeight as GrandpaWeight};
+use im_online::AuthorityId as ImOnlineId;
 use primitives::{crypto::key_types, OpaqueMetadata};
 use rstd::prelude::*;
 use runtime_primitives::traits::{
@@ -34,7 +35,7 @@ pub use balances::Call as BalancesCall;
 #[cfg(any(feature = "std", test))]
 pub use runtime_primitives::BuildStorage;
 pub use runtime_primitives::{Perbill, Permill};
-pub use srml_support::{construct_runtime, parameter_types, StorageValue};
+pub use srml_support::{construct_runtime, parameter_types, StorageMap, StorageValue};
 pub use timestamp::Call as TimestampCall;
 
 /// An index to a block.
@@ -229,7 +230,7 @@ impl balances::Trait for Runtime {
     /// The type for recording an account's balance.
     type Balance = Balance;
     /// What to do if an account's free balance gets zeroed.
-    type OnFreeBalanceZero = ();
+    type OnFreeBalanceZero = (Staking, Session);
     /// What to do if a new account is created.
     type OnNewAccount = Indices;
     /// The ubiquitous event type.
@@ -251,6 +252,97 @@ impl sudo::Trait for Runtime {
     type Proposal = Call;
 }
 
+parameter_types! {
+    pub const UncleGenerations: BlockNumber = 5;
+}
+
+impl authorship::Trait for Runtime {
+    type FindAuthor = session::FindAccountFromAuthorIndex<Self, Babe>;
+    type UncleGenerations = UncleGenerations;
+    type FilterUncle = ();
+    type EventHandler = Staking;
+}
+
+type SessionHandlers = (Grandpa, Babe, ImOnline);
+
+impl_opaque_keys! {
+    pub struct SessionKeys {
+        #[id(key_types::GRANDPA)]
+        pub grandpa: GrandpaId,
+        #[id(key_types::BABE)]
+        pub babe: BabeId,
+        #[id(key_types::IM_ONLINE)]
+        pub im_online: ImOnlineId,
+    }
+}
+
+// NOTE: `SessionHandler` and `SessionKeys` are co-dependent: One key will be used for each handler.
+// The number and order of items in `SessionHandler` *MUST* be the same number and order of keys in
+// `SessionKeys`.
+// TODO: Introduce some structure to tie these together to make it a bit less of a footgun. This
+// should be easy, since OneSessionHandler trait provides the `Key` as an associated type. #2858
+
+impl session::Trait for Runtime {
+    type OnSessionEnding = Staking;
+    type SessionHandler = SessionHandlers;
+    type ShouldEndSession = Babe;
+    type Event = Event;
+    type Keys = SessionKeys;
+    type ValidatorId = AccountId;
+    type ValidatorIdOf = staking::StashOf<Self>;
+    type SelectInitialValidators = Staking;
+}
+
+impl session::historical::Trait for Runtime {
+    type FullIdentification = staking::Exposure<AccountId, Balance>;
+    type FullIdentificationOf = staking::ExposureOf<Runtime>;
+}
+
+parameter_types! {
+    pub const SessionsPerEra: sr_staking_primitives::SessionIndex = 6;
+    pub const BondingDuration: staking::EraIndex = 24 * 28;
+}
+
+impl staking::Trait for Runtime {
+    type Currency = Balances;
+    type Time = Timestamp;
+    type CurrencyToVote = currency::CurrencyToVoteHandler;
+    type OnRewardMinted = ();
+    type Event = Event;
+    type Slash = (); // where to send the slashed funds.
+    type Reward = (); // rewards are minted from the void
+    type SessionsPerEra = SessionsPerEra;
+    type BondingDuration = BondingDuration;
+    type SessionInterface = Self;
+}
+
+impl im_online::Trait for Runtime {
+    type Call = Call;
+    type Event = Event;
+    type UncheckedExtrinsic = UncheckedExtrinsic;
+    type ReportUnresponsiveness = Offences;
+    type CurrentElectedSet = staking::CurrentElectedStashAccounts<Runtime>;
+}
+
+impl offences::Trait for Runtime {
+    type Event = Event;
+    type IdentificationTuple = session::historical::IdentificationTuple<Self>;
+    type OnOffenceHandler = Staking;
+}
+
+impl authority_discovery::Trait for Runtime {}
+
+parameter_types! {
+    pub const WindowSize: BlockNumber = 101;
+    pub const ReportLatency: BlockNumber = 1000;
+}
+
+impl finality_tracker::Trait for Runtime {
+    type OnFinalizationStalled = Grandpa;
+    type WindowSize = WindowSize;
+    type ReportLatency = ReportLatency;
+}
+
 pub mod currency;
 pub mod governance;
 use governance::{council, election, proposals};
@@ -436,12 +528,20 @@ construct_runtime!(
 		NodeBlock = opaque::Block,
 		UncheckedExtrinsic = UncheckedExtrinsic
 	{
+        // Substrate
 		System: system::{Module, Call, Storage, Config, Event},
-		Timestamp: timestamp::{Module, Call, Storage, Inherent},
 		Babe: babe::{Module, Call, Storage, Config, Inherent(Timestamp)},
-		Grandpa: grandpa::{Module, Call, Storage, Config, Event},
-		Indices: indices::{default, Config<T>},
+		Timestamp: timestamp::{Module, Call, Storage, Inherent},
+		Authorship: authorship::{Module, Call, Storage, Inherent},
+		Indices: indices,
 		Balances: balances,
+		Staking: staking::{default, OfflineWorker},
+		Session: session::{Module, Call, Storage, Event, Config<T>},
+        FinalityTracker: finality_tracker::{Module, Call, Inherent},
+		Grandpa: grandpa::{Module, Call, Storage, Config, Event},
+        ImOnline: im_online::{Module, Call, Storage, Event, ValidateUnsigned, Config},
+		AuthorityDiscovery: authority_discovery::{Module, Call, Config},
+		Offences: offences::{Module, Call, Storage, Event},
 		Sudo: sudo,
         // Joystream
 		Proposals: proposals::{Module, Call, Storage, Event<T>, Config<T>},
@@ -586,10 +686,33 @@ impl_runtime_apis! {
         }
     }
 
+    impl authority_discovery_primitives::AuthorityDiscoveryApi<Block, im_online::AuthorityId> for Runtime {
+        fn authority_id() -> Option<im_online::AuthorityId> {
+            AuthorityDiscovery::authority_id()
+        }
+        fn authorities() -> Vec<im_online::AuthorityId> {
+            AuthorityDiscovery::authorities()
+        }
+
+        fn sign(payload: Vec<u8>, authority_id: im_online::AuthorityId) -> Option<Vec<u8>> {
+            AuthorityDiscovery::sign(payload, authority_id)
+        }
+
+        fn verify(payload: Vec<u8>, signature: Vec<u8>, public_key: im_online::AuthorityId) -> bool {
+            AuthorityDiscovery::verify(payload, signature, public_key)
+        }
+    }
+
+    impl node_primitives::AccountNonceApi<Block> for Runtime {
+        fn account_nonce(account: AccountId) -> Index {
+            System::account_nonce(account)
+        }
+    }
+
     impl substrate_session::SessionKeys<Block> for Runtime {
         fn generate_session_keys(seed: Option<Vec<u8>>) -> Vec<u8> {
             let seed = seed.as_ref().map(|s| rstd::str::from_utf8(&s).expect("Seed is an utf8 string"));
-            opaque::SessionKeys::generate(seed)
+            SessionKeys::generate(seed)
         }
     }
 }

+ 6 - 4
src/service_discovery/discovery.rs

@@ -1,6 +1,8 @@
 use crate::traits::Roles;
 use codec::{Decode, Encode};
 use rstd::prelude::*;
+#[cfg(feature = "std")]
+use serde::{Deserialize, Serialize};
 
 use srml_support::{decl_event, decl_module, decl_storage, ensure, StorageMap, StorageValue};
 use system::{self, ensure_root, ensure_signed};
@@ -48,7 +50,7 @@ decl_storage! {
         /// Mapping of service providers' AccountIds to their AccountInfo
         pub AccountInfoByAccountId get(account_info_by_account_id): map T::AccountId => AccountInfo<T::BlockNumber>;
         /// Lifetime of an AccountInfo record in AccountInfoByAccountId map
-        pub DefaultLifetime get(default_lifetime) config(): T::BlockNumber = T::BlockNumber::sa(DEFAULT_LIFETIME);
+        pub DefaultLifetime get(default_lifetime) config(): T::BlockNumber = T::BlockNumber::from(DEFAULT_LIFETIME);
     }
 }
 
@@ -86,9 +88,9 @@ decl_module! {
 
             let ttl = match lifetime {
                 Some(value) => if value >= MINIMUM_LIFETIME {
-                    T::BlockNumber::sa(value)
+                    T::BlockNumber::from(value)
                 } else {
-                    T::BlockNumber::sa(MINIMUM_LIFETIME)
+                    T::BlockNumber::from(MINIMUM_LIFETIME)
                 },
                 _ => Self::default_lifetime()
             };
@@ -113,7 +115,7 @@ decl_module! {
             // decl_module! macro takes care of it.. its required for unit tests to work correctly
             // otherwise it complains the method
             ensure_root(origin)?;
-            ensure!(lifetime >= T::BlockNumber::sa(MINIMUM_LIFETIME), "discovery: default lifetime must be gte minimum lifetime");
+            ensure!(lifetime >= T::BlockNumber::from(MINIMUM_LIFETIME), "discovery: default lifetime must be gte minimum lifetime");
             <DefaultLifetime<T>>::put(lifetime);
         }