Newer
Older
// Copyright 2018 Parity Technologies (UK) Ltd.
// Substrate is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Substrate is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
//! The Substrate runtime. This can be compiled with ``#[no_std]`, ready for Wasm.
// `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256.
#![recursion_limit="256"]
#[macro_use]
extern crate sr_api as runtime_api;
extern crate sr_primitives as runtime_primitives;
#[cfg(feature = "std")]
#[macro_use]
extern crate serde_derive;
extern crate substrate_primitives;
#[cfg_attr(not(feature = "std"), macro_use)]
extern crate sr_std as rstd;
extern crate srml_balances as balances;
extern crate srml_consensus as consensus;
extern crate srml_contract as contract;
extern crate srml_council as council;
extern crate srml_democracy as democracy;
extern crate srml_executive as executive;
extern crate srml_session as session;
extern crate srml_staking as staking;
extern crate srml_system as system;
extern crate srml_timestamp as timestamp;
extern crate srml_treasury as treasury;
extern crate sr_version as version;
extern crate node_primitives;
use node_primitives::{
AccountId, AccountIndex, Balance, BlockNumber, Hash, Index,
SessionKey, Signature, InherentData, Timestamp as TimestampType
};
use runtime_api::{BlockBuilderError, runtime::*};
use runtime_primitives::ApplyResult;
use runtime_primitives::transaction_validity::TransactionValidity;
use runtime_primitives::traits::{Convert, BlakeTwo256, DigestItem, Block as BlockT};
use version::{RuntimeVersion, ApiId};
use council::{motions as council_motions, voting as council_voting};
#[cfg(feature = "std")]
use council::seats as council_seats;
#[cfg(any(feature = "std", test))]
use version::NativeVersion;
pub use runtime_primitives::BuildStorage;
pub use consensus::Call as ConsensusCall;
pub use timestamp::Call as TimestampCall;
pub use balances::Call as BalancesCall;
pub use runtime_primitives::{Permill, Perbill};
pub use timestamp::BlockPeriod;
pub use srml_support::StorageValue;
const TIMESTAMP_SET_POSITION: u32 = 0;
const NOTE_OFFLINE_POSITION: u32 = 1;
const INHERENT: ApiId = *b"inherent";
const VALIDATX: ApiId = *b"validatx";
/// Runtime version.
pub const VERSION: RuntimeVersion = RuntimeVersion {
spec_name: ver_str!("node"),
impl_name: ver_str!("substrate-node"),
apis: apis_vec!([(INHERENT, 1), (VALIDATX, 1)]),
/// Native version.
#[cfg(any(feature = "std", test))]
pub fn native_version() -> NativeVersion {
NativeVersion {
runtime_version: VERSION,
can_author_with: Default::default(),
}
}
type Index = Index;
type BlockNumber = BlockNumber;
type Hash = Hash;
type Hashing = BlakeTwo256;
type Header = generic::Header<BlockNumber, BlakeTwo256, Log>;
Svyatoslav Nikolsky
committed
type Log = Log;
type Balance = Balance;
type AccountIndex = AccountIndex;
type EnsureAccountLiquid = Staking;
type Event = Event;
}
const NOTE_OFFLINE_POSITION: u32 = NOTE_OFFLINE_POSITION;
type SessionKey = SessionKey;
type OnOfflineValidator = Staking;
const TIMESTAMP_SET_POSITION: u32 = TIMESTAMP_SET_POSITION;
/// Session key conversion.
pub struct SessionKeyConversion;
impl Convert<AccountId, SessionKey> for SessionKeyConversion {
fn convert(a: AccountId) -> SessionKey {
type ConvertAccountIdToSessionKey = SessionKeyConversion;
type OnSessionChange = Staking;
impl council::Trait for Runtime {
type Event = Event;
}
impl council::voting::Trait for Runtime {
type Event = Event;
}
impl council::motions::Trait for Runtime {
type Origin = Origin;
type Proposal = Call;
type Event = Event;
}
impl treasury::Trait for Runtime {
type ApproveOrigin = council_motions::EnsureMembers<_4>;
type RejectOrigin = council_motions::EnsureMembers<_2>;
type Event = Event;
}
impl contract::Trait for Runtime {
type Gas = u64;
type DetermineContractAddress = contract::SimpleAddressDeterminator<Runtime>;
Svyatoslav Nikolsky
committed
type Hash = Hash;
fn as_authorities_change(&self) -> Option<&[Self::AuthorityId]> {
match self.0 {
InternalLog::consensus(ref item) => item.as_authorities_change(),
Svyatoslav Nikolsky
committed
_ => None,
}
}
fn as_changes_trie_root(&self) -> Option<&Self::Hash> {
match self.0 {
InternalLog::system(ref item) => item.as_changes_trie_root(),
_ => None,
Svyatoslav Nikolsky
committed
pub enum Runtime with Log(InternalLog: DigestItem<Hash, SessionKey>) {
System: system::{default, Log(ChangesTrieRoot)},
Consensus: consensus::{Module, Call, Storage, Config, Log(AuthoritiesChange)},
Balances: balances,
Timestamp: timestamp::{Module, Call, Storage, Config},
Session: session,
Staking: staking,
Democracy: democracy,
Council: council::{Module, Call, Storage, Event<T>},
CouncilVoting: council_voting,
CouncilMotions: council_motions::{Module, Call, Storage, Event<T>, Origin},
Contract: contract::{Module, Call, Config, Event<T>},
/// The address format for describing accounts.
pub use balances::address::Address as RawAddress;
pub type Address = balances::Address<Runtime>;
pub type Header = generic::Header<BlockNumber, BlakeTwo256, Log>;
pub type Block = generic::Block<Header, UncheckedExtrinsic>;
/// A Block signed with a Justification
pub type SignedBlock = generic::SignedBlock<Header, UncheckedExtrinsic>;
/// BlockId type as expected by this runtime.
pub type BlockId = generic::BlockId<Block>;
/// Unchecked extrinsic type as expected by this runtime.
pub type UncheckedExtrinsic = generic::UncheckedMortalExtrinsic<Address, Index, Call, Signature>;
/// Extrinsic type that has already been checked.
pub type CheckedExtrinsic = generic::CheckedExtrinsic<AccountId, Index, Call>;
/// Executive: handles dispatch to the various modules.
pub type Executive = executive::Executive<Runtime, Block, balances::ChainContext<Runtime>, Balances, AllModules>;
impl_apis! {
impl Core<Block, SessionKey> for Runtime {
fn version() -> RuntimeVersion {
VERSION
}
fn authorities() -> Vec<SessionKey> {
Consensus::authorities()
}
fn execute_block(block: Block) {
Executive::execute_block(block)
}
}
impl Metadata for Runtime {
fn metadata() -> Vec<u8> {
Runtime::metadata()
}
impl BlockBuilder<Block, InherentData, UncheckedExtrinsic, InherentData> for Runtime {
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
fn initialise_block(header: <Block as BlockT>::Header) {
Executive::initialise_block(&header)
}
fn apply_extrinsic(extrinsic: <Block as BlockT>::Extrinsic) -> ApplyResult {
Executive::apply_extrinsic(extrinsic)
}
fn finalise_block() -> <Block as BlockT>::Header {
Executive::finalise_block()
}
fn inherent_extrinsics(data: InherentData) -> Vec<UncheckedExtrinsic> {
let mut inherent = vec![generic::UncheckedMortalExtrinsic::new_unsigned(
Call::Timestamp(TimestampCall::set(data.timestamp))
)];
if !data.offline_indices.is_empty() {
inherent.push(generic::UncheckedMortalExtrinsic::new_unsigned(
Call::Consensus(ConsensusCall::note_offline(data.offline_indices))
));
}
inherent
}
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
fn check_inherents(block: Block, data: InherentData) -> Result<(), BlockBuilderError> {
// TODO: v1: should be automatically gathered
// Timestamp module...
const MAX_TIMESTAMP_DRIFT: TimestampType = 60;
let xt = block.extrinsics.get(TIMESTAMP_SET_POSITION as usize)
.ok_or_else(|| BlockBuilderError::Generic("No valid timestamp inherent in block".into()))?;
let t = match (xt.is_signed(), &xt.function) {
(false, Call::Timestamp(TimestampCall::set(t))) => t,
_ => return Err(BlockBuilderError::Generic("No valid timestamp inherent in block".into())),
};
if *t > data.timestamp + MAX_TIMESTAMP_DRIFT {
return Err(BlockBuilderError::TimestampInFuture(*t))
}
// Offline indices
let noted_offline =
block.extrinsics.get(NOTE_OFFLINE_POSITION as usize).and_then(|xt| match xt.function {
Call::Consensus(ConsensusCall::note_offline(ref x)) => Some(&x[..]),
_ => None,
}).unwrap_or(&[]);
noted_offline.iter().try_for_each(|n|
if !data.offline_indices.contains(n) {
Err(BlockBuilderError::Generic("Online node marked offline".into()))
} else {
Ok(())
}
)
}
fn random_seed() -> <Block as BlockT>::Hash {
System::random_seed()
}
}
impl OldTxQueue<AccountId, Index, Address, AccountId> for Runtime {
fn account_nonce(account: AccountId) -> Index {
System::account_nonce(&account)
}
fn lookup_address(address: Address) -> Option<AccountId> {
Balances::lookup_address(address)
}
}
impl TaggedTransactionQueue<Block, TransactionValidity> for Runtime {
fn validate_transaction(tx: <Block as BlockT>::Extrinsic) -> TransactionValidity {
Executive::validate_transaction(tx)
}
}
impl Miscellaneous<AccountId, u64> for Runtime {
fn validator_count() -> u32 {
Session::validator_count()
}
fn validators() -> Vec<AccountId> {
Session::validators()
}
fn timestamp() -> u64 {
Timestamp::get()
}
}