Files
pezkuwi-subxt/substrate/node/runtime/src/lib.rs
T
Max Inden cf80af9255 core/consensus,node/runtime: Declare and implement authorities endpoint (#3207)
The goal of the commit is to be able to retrieve the current set of
authorities without needing to know the concrete consensus mechanism in
place.

In order to achieve the above this commit introduces the
`core/consensus/common/primitives` crate, declaring the `ConsensusApi`
runtime API. In addition it implements the above mentioned trait
definition in `node/runtime` by returning the current authorities of the
BABE consensus mechanism.
2019-07-29 08:39:47 -04:00

548 lines
18 KiB
Rust

// Copyright 2018-2019 Parity Technologies (UK) Ltd.
// This file is part of Substrate.
// 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.
#![cfg_attr(not(feature = "std"), no_std)]
// `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256.
#![recursion_limit="256"]
use rstd::prelude::*;
use support::{
construct_runtime, parameter_types, traits::{SplitTwoWays, Currency}
};
use substrate_primitives::u32_trait::{_1, _2, _3, _4};
use node_primitives::{
AccountId, AccountIndex, Balance, BlockNumber, Hash, Index,
Moment, Signature,
};
use babe::{AuthorityId as BabeId};
use grandpa::fg_primitives::{self, ScheduledChange};
use client::{
block_builder::api::{self as block_builder_api, InherentData, CheckInherentsResult},
runtime_api as client_api, impl_runtime_apis
};
use runtime_primitives::{ApplyResult, impl_opaque_keys, generic, create_runtime_str, key_types};
use runtime_primitives::transaction_validity::TransactionValidity;
use runtime_primitives::weights::Weight;
use runtime_primitives::traits::{
BlakeTwo256, Block as BlockT, DigestFor, NumberFor, StaticLookup,
};
use version::RuntimeVersion;
use elections::VoteIndex;
#[cfg(any(feature = "std", test))]
use version::NativeVersion;
use substrate_primitives::OpaqueMetadata;
use grandpa::{AuthorityId as GrandpaId, AuthorityWeight as GrandpaWeight};
use finality_tracker::{DEFAULT_REPORT_LATENCY, DEFAULT_WINDOW_SIZE};
#[cfg(any(feature = "std", test))]
pub use runtime_primitives::BuildStorage;
pub use timestamp::Call as TimestampCall;
pub use balances::Call as BalancesCall;
pub use contracts::Gas;
pub use runtime_primitives::{Permill, Perbill};
pub use support::StorageValue;
pub use staking::StakerStatus;
/// Implementations of some helper traits passed into runtime modules as associated types.
pub mod impls;
use impls::{CurrencyToVoteHandler, WeightMultiplierUpdateHandler, Author, WeightToFee};
/// Constant values used within the runtime.
pub mod constants;
use constants::{time::*, currency::*};
// Make the WASM binary available.
#[cfg(feature = "std")]
include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));
/// Runtime version.
pub const VERSION: RuntimeVersion = RuntimeVersion {
spec_name: create_runtime_str!("node"),
impl_name: create_runtime_str!("substrate-node"),
authoring_version: 10,
// Per convention: if the runtime behavior changes, increment spec_version
// and set impl_version to equal spec_version. If only runtime
// implementation changes and behavior does not, then leave spec_version as
// is and increment impl_version.
spec_version: 122,
impl_version: 123,
apis: RUNTIME_API_VERSIONS,
};
/// Native version.
#[cfg(any(feature = "std", test))]
pub fn native_version() -> NativeVersion {
NativeVersion {
runtime_version: VERSION,
can_author_with: Default::default(),
}
}
type NegativeImbalance = <Balances as Currency<AccountId>>::NegativeImbalance;
pub type DealWithFees = SplitTwoWays<
Balance,
NegativeImbalance,
_4, Treasury, // 4 parts (80%) goes to the treasury.
_1, Author, // 1 part (20%) goes to the block author.
>;
parameter_types! {
pub const BlockHashCount: BlockNumber = 250;
pub const MaximumBlockWeight: Weight = 1_000_000_000;
pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75);
pub const MaximumBlockLength: u32 = 5 * 1024 * 1024;
}
impl system::Trait for Runtime {
type Origin = Origin;
type Index = Index;
type BlockNumber = BlockNumber;
type Hash = Hash;
type Hashing = BlakeTwo256;
type AccountId = AccountId;
type Lookup = Indices;
type Header = generic::Header<BlockNumber, BlakeTwo256>;
type WeightMultiplierUpdate = WeightMultiplierUpdateHandler;
type Event = Event;
type BlockHashCount = BlockHashCount;
type MaximumBlockWeight = MaximumBlockWeight;
type MaximumBlockLength = MaximumBlockLength;
type AvailableBlockRatio = AvailableBlockRatio;
}
parameter_types! {
pub const EpochDuration: u64 = EPOCH_DURATION_IN_SLOTS;
}
impl babe::Trait for Runtime {
type EpochDuration = EpochDuration;
}
impl indices::Trait for Runtime {
type AccountIndex = AccountIndex;
type IsDeadAccount = Balances;
type ResolveHint = indices::SimpleResolveHint<Self::AccountId, Self::AccountIndex>;
type Event = Event;
}
parameter_types! {
pub const ExistentialDeposit: Balance = 1 * DOLLARS;
pub const TransferFee: Balance = 1 * CENTS;
pub const CreationFee: Balance = 1 * CENTS;
pub const TransactionBaseFee: Balance = 1 * CENTS;
pub const TransactionByteFee: Balance = 10 * MILLICENTS;
}
impl balances::Trait for Runtime {
type Balance = Balance;
type OnFreeBalanceZero = ((Staking, Contracts), Session);
type OnNewAccount = Indices;
type Event = Event;
type TransactionPayment = DealWithFees;
type DustRemoval = ();
type TransferPayment = ();
type ExistentialDeposit = ExistentialDeposit;
type TransferFee = TransferFee;
type CreationFee = CreationFee;
type TransactionBaseFee = TransactionBaseFee;
type TransactionByteFee = TransactionByteFee;
type WeightToFee = WeightToFee;
}
parameter_types! {
pub const MinimumPeriod: Moment = SLOT_DURATION / 2;
}
impl timestamp::Trait for Runtime {
type Moment = Moment;
type OnTimestampSet = Babe;
type MinimumPeriod = MinimumPeriod;
}
parameter_types! {
pub const UncleGenerations: u64 = 0;
}
// TODO: #2986 implement this properly
impl authorship::Trait for Runtime {
type FindAuthor = ();
type UncleGenerations = UncleGenerations;
type FilterUncle = ();
type EventHandler = Staking;
}
type SessionHandlers = (Grandpa, Babe, ImOnline);
impl_opaque_keys! {
pub struct SessionKeys {
#[id(key_types::ED25519)]
pub ed25519: GrandpaId,
#[id(key_types::SR25519)]
pub sr25519: BabeId,
}
}
// 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: session::SessionIndex = 6;
pub const BondingDuration: staking::EraIndex = 24 * 28;
}
impl staking::Trait for Runtime {
type Currency = Balances;
type Time = Timestamp;
type CurrencyToVote = CurrencyToVoteHandler;
type OnRewardMinted = Treasury;
type Event = Event;
type Slash = ();
type Reward = ();
type SessionsPerEra = SessionsPerEra;
type BondingDuration = BondingDuration;
type SessionInterface = Self;
}
parameter_types! {
pub const LaunchPeriod: BlockNumber = 28 * 24 * 60 * MINUTES;
pub const VotingPeriod: BlockNumber = 28 * 24 * 60 * MINUTES;
pub const EmergencyVotingPeriod: BlockNumber = 3 * 24 * 60 * MINUTES;
pub const MinimumDeposit: Balance = 100 * DOLLARS;
pub const EnactmentPeriod: BlockNumber = 30 * 24 * 60 * MINUTES;
pub const CooloffPeriod: BlockNumber = 30 * 24 * 60 * MINUTES;
}
impl democracy::Trait for Runtime {
type Proposal = Call;
type Event = Event;
type Currency = Balances;
type EnactmentPeriod = EnactmentPeriod;
type LaunchPeriod = LaunchPeriod;
type VotingPeriod = VotingPeriod;
type EmergencyVotingPeriod = EmergencyVotingPeriod;
type MinimumDeposit = MinimumDeposit;
type ExternalOrigin = collective::EnsureProportionAtLeast<_1, _2, AccountId, CouncilInstance>;
type ExternalMajorityOrigin = collective::EnsureProportionAtLeast<_2, _3, AccountId, CouncilInstance>;
type ExternalPushOrigin = collective::EnsureProportionAtLeast<_2, _3, AccountId, TechnicalInstance>;
type EmergencyOrigin = collective::EnsureProportionAtLeast<_1, _1, AccountId, CouncilInstance>;
type CancellationOrigin = collective::EnsureProportionAtLeast<_2, _3, AccountId, CouncilInstance>;
type VetoOrigin = collective::EnsureMember<AccountId, CouncilInstance>;
type CooloffPeriod = CooloffPeriod;
}
type CouncilInstance = collective::Instance1;
impl collective::Trait<CouncilInstance> for Runtime {
type Origin = Origin;
type Proposal = Call;
type Event = Event;
}
parameter_types! {
pub const CandidacyBond: Balance = 10 * DOLLARS;
pub const VotingBond: Balance = 1 * DOLLARS;
pub const VotingFee: Balance = 2 * DOLLARS;
pub const PresentSlashPerVoter: Balance = 1 * CENTS;
pub const CarryCount: u32 = 6;
// one additional vote should go by before an inactive voter can be reaped.
pub const InactiveGracePeriod: VoteIndex = 1;
pub const ElectionsVotingPeriod: BlockNumber = 2 * DAYS;
pub const DecayRatio: u32 = 0;
}
impl elections::Trait for Runtime {
type Event = Event;
type Currency = Balances;
type BadPresentation = ();
type BadReaper = ();
type BadVoterIndex = ();
type LoserCandidate = ();
type ChangeMembers = Council;
type CandidacyBond = CandidacyBond;
type VotingBond = VotingBond;
type VotingFee = VotingFee;
type PresentSlashPerVoter = PresentSlashPerVoter;
type CarryCount = CarryCount;
type InactiveGracePeriod = InactiveGracePeriod;
type VotingPeriod = ElectionsVotingPeriod;
type DecayRatio = DecayRatio;
}
type TechnicalInstance = collective::Instance2;
impl collective::Trait<TechnicalInstance> for Runtime {
type Origin = Origin;
type Proposal = Call;
type Event = Event;
}
parameter_types! {
pub const ProposalBond: Permill = Permill::from_percent(5);
pub const ProposalBondMinimum: Balance = 1 * DOLLARS;
pub const SpendPeriod: BlockNumber = 1 * DAYS;
pub const Burn: Permill = Permill::from_percent(50);
}
impl treasury::Trait for Runtime {
type Currency = Balances;
type ApproveOrigin = collective::EnsureMembers<_4, AccountId, CouncilInstance>;
type RejectOrigin = collective::EnsureMembers<_2, AccountId, CouncilInstance>;
type Event = Event;
type MintedForSpending = ();
type ProposalRejection = ();
type ProposalBond = ProposalBond;
type ProposalBondMinimum = ProposalBondMinimum;
type SpendPeriod = SpendPeriod;
type Burn = Burn;
}
parameter_types! {
pub const ContractTransferFee: Balance = 1 * CENTS;
pub const ContractCreationFee: Balance = 1 * CENTS;
pub const ContractTransactionBaseFee: Balance = 1 * CENTS;
pub const ContractTransactionByteFee: Balance = 10 * MILLICENTS;
pub const ContractFee: Balance = 1 * CENTS;
}
impl contracts::Trait for Runtime {
type Currency = Balances;
type Call = Call;
type Event = Event;
type DetermineContractAddress = contracts::SimpleAddressDeterminator<Runtime>;
type ComputeDispatchFee = contracts::DefaultDispatchFeeComputor<Runtime>;
type TrieIdGenerator = contracts::TrieIdFromParentCounter<Runtime>;
type GasPayment = ();
type SignedClaimHandicap = contracts::DefaultSignedClaimHandicap;
type TombstoneDeposit = contracts::DefaultTombstoneDeposit;
type StorageSizeOffset = contracts::DefaultStorageSizeOffset;
type RentByteFee = contracts::DefaultRentByteFee;
type RentDepositOffset = contracts::DefaultRentDepositOffset;
type SurchargeReward = contracts::DefaultSurchargeReward;
type TransferFee = ContractTransferFee;
type CreationFee = ContractCreationFee;
type TransactionBaseFee = ContractTransactionBaseFee;
type TransactionByteFee = ContractTransactionByteFee;
type ContractFee = ContractFee;
type CallBaseFee = contracts::DefaultCallBaseFee;
type CreateBaseFee = contracts::DefaultCreateBaseFee;
type MaxDepth = contracts::DefaultMaxDepth;
type MaxValueSize = contracts::DefaultMaxValueSize;
type BlockGasLimit = contracts::DefaultBlockGasLimit;
}
impl sudo::Trait for Runtime {
type Event = Event;
type Proposal = Call;
}
impl im_online::Trait for Runtime {
type AuthorityId = BabeId;
type Call = Call;
type Event = Event;
type SessionsPerEra = SessionsPerEra;
type UncheckedExtrinsic = UncheckedExtrinsic;
type IsValidAuthorityId = Babe;
}
impl grandpa::Trait for Runtime {
type Event = Event;
}
parameter_types! {
pub const WindowSize: BlockNumber = DEFAULT_WINDOW_SIZE.into();
pub const ReportLatency: BlockNumber = DEFAULT_REPORT_LATENCY.into();
}
impl finality_tracker::Trait for Runtime {
type OnFinalizationStalled = Grandpa;
type WindowSize = WindowSize;
type ReportLatency = ReportLatency;
}
construct_runtime!(
pub enum Runtime where
Block = Block,
NodeBlock = node_primitives::Block,
UncheckedExtrinsic = UncheckedExtrinsic
{
System: system::{Module, Call, Storage, Config, Event},
Babe: babe::{Module, Call, Storage, Config, Inherent(Timestamp)},
Timestamp: timestamp::{Module, Call, Storage, Inherent},
Authorship: authorship::{Module, Call, Storage},
Indices: indices,
Balances: balances,
Staking: staking::{default, OfflineWorker},
Session: session::{Module, Call, Storage, Event, Config<T>},
Democracy: democracy::{Module, Call, Storage, Config, Event<T>},
Council: collective::<Instance1>::{Module, Call, Storage, Origin<T>, Event<T>, Config<T>},
TechnicalCommittee: collective::<Instance2>::{Module, Call, Storage, Origin<T>, Event<T>, Config<T>},
Elections: elections::{Module, Call, Storage, Event<T>, Config<T>},
FinalityTracker: finality_tracker::{Module, Call, Inherent},
Grandpa: grandpa::{Module, Call, Storage, Config, Event},
Treasury: treasury::{Module, Call, Storage, Event<T>},
Contracts: contracts,
Sudo: sudo,
ImOnline: im_online::{default, ValidateUnsigned},
}
);
/// The address format for describing accounts.
pub type Address = <Indices as StaticLookup>::Source;
/// Block header type as expected by this runtime.
pub type Header = generic::Header<BlockNumber, BlakeTwo256>;
/// Block type as expected by this runtime.
pub type Block = generic::Block<Header, UncheckedExtrinsic>;
/// A Block signed with a Justification
pub type SignedBlock = generic::SignedBlock<Block>;
/// BlockId type as expected by this runtime.
pub type BlockId = generic::BlockId<Block>;
/// The SignedExtension to the basic transaction logic.
pub type SignedExtra = (
system::CheckEra<Runtime>,
system::CheckNonce<Runtime>,
system::CheckWeight<Runtime>,
balances::TakeFees<Runtime>
);
/// Unchecked extrinsic type as expected by this runtime.
pub type UncheckedExtrinsic = generic::UncheckedExtrinsic<Address, Call, Signature, SignedExtra>;
/// Extrinsic type that has already been checked.
pub type CheckedExtrinsic = generic::CheckedExtrinsic<AccountId, Call, SignedExtra>;
/// Executive: handles dispatch to the various modules.
pub type Executive = executive::Executive<Runtime, Block, system::ChainContext<Runtime>, Runtime, AllModules>;
impl_runtime_apis! {
impl client_api::Core<Block> for Runtime {
fn version() -> RuntimeVersion {
VERSION
}
fn execute_block(block: Block) {
Executive::execute_block(block)
}
fn initialize_block(header: &<Block as BlockT>::Header) {
Executive::initialize_block(header)
}
}
impl client_api::Metadata<Block> for Runtime {
fn metadata() -> OpaqueMetadata {
Runtime::metadata().into()
}
}
impl block_builder_api::BlockBuilder<Block> for Runtime {
fn apply_extrinsic(extrinsic: <Block as BlockT>::Extrinsic) -> ApplyResult {
Executive::apply_extrinsic(extrinsic)
}
fn finalize_block() -> <Block as BlockT>::Header {
Executive::finalize_block()
}
fn inherent_extrinsics(data: InherentData) -> Vec<<Block as BlockT>::Extrinsic> {
data.create_extrinsics()
}
fn check_inherents(block: Block, data: InherentData) -> CheckInherentsResult {
data.check_extrinsics(&block)
}
fn random_seed() -> <Block as BlockT>::Hash {
System::random_seed()
}
}
impl client_api::TaggedTransactionQueue<Block> for Runtime {
fn validate_transaction(tx: <Block as BlockT>::Extrinsic) -> TransactionValidity {
Executive::validate_transaction(tx)
}
}
impl offchain_primitives::OffchainWorkerApi<Block> for Runtime {
fn offchain_worker(number: NumberFor<Block>) {
Executive::offchain_worker(number)
}
}
impl fg_primitives::GrandpaApi<Block> for Runtime {
fn grandpa_pending_change(digest: &DigestFor<Block>)
-> Option<ScheduledChange<NumberFor<Block>>>
{
Grandpa::pending_change(digest)
}
fn grandpa_forced_change(digest: &DigestFor<Block>)
-> Option<(NumberFor<Block>, ScheduledChange<NumberFor<Block>>)>
{
Grandpa::forced_change(digest)
}
fn grandpa_authorities() -> Vec<(GrandpaId, GrandpaWeight)> {
Grandpa::grandpa_authorities()
}
}
impl babe_primitives::BabeApi<Block> for Runtime {
fn startup_data() -> babe_primitives::BabeConfiguration {
// The choice of `c` parameter is done in accordance to
// the slot duration and expected target block time, for
// safely resisting network delays of maximum two seconds.
// <https://research.web3.foundation/en/latest/polkadot/BABE/Babe/#6-practical-results>
babe_primitives::BabeConfiguration {
median_required_blocks: 1000,
slot_duration: Babe::slot_duration(),
c: (278, 1000),
}
}
fn epoch() -> babe_primitives::Epoch {
babe_primitives::Epoch {
start_slot: Babe::epoch_start_slot(),
authorities: Babe::authorities(),
epoch_index: Babe::epoch_index(),
randomness: Babe::randomness(),
duration: EpochDuration::get(),
}
}
}
impl consensus_primitives::ConsensusApi<Block, babe_primitives::AuthorityId> for Runtime {
fn authorities() -> Vec<babe_primitives::AuthorityId> {
Babe::authorities().into_iter().map(|(a, _)| a).collect()
}
}
}